-
Notifications
You must be signed in to change notification settings - Fork 806
Open
Labels
Description
Stack trace
2026-01-24 10:30:58.816 [error] panic handling request textDocument/completion: runtime error: invalid memory address or nil pointer dereference
goroutine 40293 [running]:
runtime/debug.Stack()
runtime/debug/stack.go:26 +0x64
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0x40001b6e08, {0x861a0?, 0x4005051500?}, 0x400d5bc660)
github.com/microsoft/typescript-go/internal/lsp/server.go:777 +0x40
panic({0x77e1e0?, 0x12b5a00?})
runtime/panic.go:783 +0x120
github.com/microsoft/typescript-go/internal/ast.(*Node).IsTypeOnly(...)
github.com/microsoft/typescript-go/internal/ast/ast.go:923
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getImportStatementCompletionInfo(0x401e94f280, 0x40161cb740, 0x4003e343c0?)
github.com/microsoft/typescript-go/internal/ls/completions.go:5110 +0x408
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData(0x401e94f280, {0xc422a8, 0x4013391860}, 0x401ab6e608, 0x4013387508, 0xa7, 0x40076b9a00)
github.com/microsoft/typescript-go/internal/ls/completions.go:528 +0x25c
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionsAtPosition(0x401e94f280, {0xc422a8, 0x4013391860}, 0x4013387508, 0xa7, 0x0)
github.com/microsoft/typescript-go/internal/ls/completions.go:347 +0x284
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).ProvideCompletion(0x401e94f280, {0xc422a8, 0x40133917a0}, {0x40000ce080?, 0x40133917a0?}, {0xce080?, 0x40?}, 0x4011d69370)
github.com/microsoft/typescript-go/internal/ls/completions.go:47 +0xd0
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleCompletion(0x4021c0a7e0?, {0xc422a8?, 0x40133917a0?}, 0x40000ce080?, 0xffff9c527f30?)
github.com/microsoft/typescript-go/internal/lsp/server.go:1095 +0x3c
github.com/microsoft/typescript-go/internal/lsp.init.func1.registerLanguageServiceWithAutoImportsRequestHandler[...].28({0xc422a8, 0x40133917a0}, 0x400d5bc660)
github.com/microsoft/typescript-go/internal/lsp/server.go:682 +0xf4
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleRequestOrNotification(0x40001b6e08, {0xc422e0?, 0x40151938b0?}, 0x400d5bc660)
github.com/microsoft/typescript-go/internal/lsp/server.go:531 +0x170
github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop.func1()
github.com/microsoft/typescript-go/internal/lsp/server.go:414 +0x34
created by github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop in goroutine 6
github.com/microsoft/typescript-go/internal/lsp/server.go:438 +0x7d8
2026-01-24 10:30:58.816 [error] Request textDocument/completion failed.
Message: InternalError: panic handling request textDocument/completion: runtime error: invalid memory address or nil pointer dereference
Code: -32603
Steps to reproduce
I was typing right here at the top. Seems pretty consistent to reproduce unlike other crashes I've experienced. Crashes right when I type the r in super
import type { CacheInvalidationOptions, CacheProvider, CacheEntry } from '../types'
import { Redis } from 'ioredis'
import { getTotalTtl } from '../utils'
import super // ⚠️ I was typing here
export class RedisCacheProvider implements CacheProvider {
private readonly redis: Redis
constructor(options: RedisCacheProviderOptions) {
this.redis = new Redis(options.url)
}
async get(key: string) {
const entryJson = await this.redis.get(formatQueryKey(key))
if (!entryJson) {
return undefined
}
return JSON.parse(entryJson) as CacheEntry
}
async set(key: string, entry: CacheEntry) {
const multi = this.redis.multi()
const formattedKey = formatQueryKey(key)
multi.set(formattedKey, JSON.stringify(entry))
const totalTtl = getTotalTtl(entry)
if (totalTtl > 0) {
multi.expire(formattedKey, totalTtl)
}
if (entry.options.tags) {
for (const tag of entry.options.tags) {
const formattedTagKey = formatTagKey(tag)
multi.sadd(formattedTagKey, formattedKey)
if (totalTtl > 0) {
multi.expire(formattedTagKey, totalTtl, 'GT')
multi.expire(formattedTagKey, totalTtl, 'NX')
}
}
}
await multi.exec()
}
async invalidate(options: CacheInvalidationOptions) {
if (options.tags && options.tags.length > 0) {
await Promise.all(
options.tags.map(tag => {
return new Promise((resolve, reject) => {
const stream = this.redis.sscanStream(formatTagKey(tag), {
count: 100,
})
stream.on('data', async (keys: string[]) => {
if (keys.length > 1) {
await this.redis.del(...keys)
}
})
stream.on('error', reject)
stream.on('end', resolve)
})
}),
)
}
}
async invalidateAll() {
await new Promise((resolve, reject) => {
const stream = this.redis.scanStream({
count: 100,
match: 'zenstack:cache:*',
})
stream.on('data', async (keys: string[]) => {
if (keys.length > 1) {
await this.redis.del(...keys)
}
})
stream.on('error', reject)
stream.on('end', resolve)
})
}
}
export type RedisCacheProviderOptions = {
url: string
}
function formatQueryKey(key: string) {
return `zenstack:cache:query:${key}`
}
function formatTagKey(key: string) {
return `zenstack:cache:tag:${key}`
}