🌐 AI搜索 & 代理 主页
Skip to content

TypeScript Language Server Hangs on Completion Resolution On Enter Key Pressed #1014

@babucarr32

Description

@babucarr32

Environment

  • Editor: Helix (version 25.07.1 (a05c151b))
  • TypeScript version: 5.0.0
  • Language Server: TypeScript LSP

Issue Description

The TypeScript language server frequently hangs when resolving completion details, specifically during foo.bar style autocompletion. The hang occurs in the interruptGetErr call and can last 15-32 seconds before timing out.

Reproduction Steps

  1. Open a TypeScript file in Helix
  2. Type foo. to trigger completion
  3. Select a completion item that requires detail resolution
  4. Hit enter
  5. Language server hangs for ~18 seconds

The issue appears to be in the completion resolution pipeline:

// src/lsp-server.ts
async completionResolve(item: lsp.CompletionItem, token?: lsp.CancellationToken): Promise<lsp.CompletionItem> {
    // ...
    const response = await this.tsClient.interruptGetErr(() => 
        this.tsClient.execute(CommandTypes.CompletionDetails, cachedData, token)
    );
    // ...
}

Personal debugging log . See time difference between startTime and endTime

{"serverState":1,"running":true,"errored":false,"none":false}
{"serverState":1,"running":true,"errored":false,"none":false}
{"command":"completionEntryDetails","cachedData":{"file":"/path/to/project/users-table/columns.tsx","line":14,"offset":26,"entryNames":["staticStatusText"]},"token":{"_isCancelled":false}}
{"startTime":"Wed Sep 24 2025 20:32:37 GMT+0000 (Greenwich Mean Time)"}
{"serverState":1,"running":true,"errored":false,"none":false}
{"serverState":1,"running":true,"errored":false,"none":false}
{"command":"completionEntryDetails","cachedData":{"file":"/path/to/project/users-table/columns.tsx","line":14,"offset":26,"entryNames":["staticStatusText"]},"token":{"_isCancelled":false}}
{"startTime":"Wed Sep 24 2025 20:32:37 GMT+0000 (Greenwich Mean Time)"}
{"serverState":1,"running":true,"errored":false,"none":false}
{"serverState":1,"running":true,"errored":false,"none":false}
{"endTime":"Wed Sep 24 2025 20:32:55 GMT+0000 (Greenwich Mean Time)"}
Returned item
{"data":{"file":"/path/to/project/users-table/columns.tsx","line":14,"offset":26,"entryNames":["staticStatusText"]},"kind":5,"label":"staticStatusText","sortText":"11","textEdit":{"insert":{"end":{"character":25,"line":13},"start":{"character":16,"line":13}},"newText":"staticStatusText","replace":{"end":{"character":25,"line":13},"start":{"character":16,"line":13}}},"detail":"(property) staticStatusText: (accessor: AccessorEntity<Transaction>, config: StatusColumnConfig) => ColumnDef<Transaction, unknown>","documentation":{"kind":"markdown","value":"Status column using Status component"}}
{"endTime":"Wed Sep 24 2025 20:32:55 GMT+0000 (Greenwich Mean Time)"}
Returned item
{"data":{"file":"/path/to/project/users-table/columns.tsx","line":14,"offset":26,"entryNames":["staticStatusText"]},"kind":5,"label":"staticStatusText","sortText":"11","textEdit":{"insert":{"end":{"character":25,"line":13},"start":{"character":16,"line":13}},"newText":"staticStatusText","replace":{"end":{"character":25,"line":13},"start":{"character":16,"line":13}}},"detail":"(property) staticStatusText: (accessor: AccessorEntity<Transaction>, config: StatusColumnConfig) => ColumnDef<Transaction, unknown>","documentation":{"kind":"markdown","value":"Status column using Status component"}}
{"serverState":1,"running":true,"errored":false,"none":false}

Logs from helix (~/.cache/helix/helix.log)

 2025-09-24T21:46:40.643 helix_lsp::transport [INFO] typescript-language-server -> {"jsonrpc":"2.0","method":"completionItem/resolve","params":{"data":{"cacheId":31},"filterText":".staticStatusText","kind":5,"label":"staticStatusText","sortText":"11","textEdit":{"newText":".staticStatusText","range":{"end":{"character":16,"line":12},"start":{"character":15,"line":12}}}},"id":6}
2025-09-24T21:46:40.754 helix_lsp::transport [INFO] typescript-language-server -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":22,"line":12},"start":{"character":15,"line":12}},"text":"."}],"textDocument":{"uri":"file:///file/path/users-table/columns.tsx","version":11}}}
2025-09-24T21:46:40.754 helix_lsp::transport [INFO] vscode-eslint-language-server -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":22,"line":12},"start":{"character":15,"line":12}},"text":"."}],"textDocument":{"uri":"file:///file/path/users-table/columns.tsx","version":11}}}
2025-09-24T21:46:40.754 helix_lsp::transport [INFO] typescript-language-server -> {"jsonrpc":"2.0","method":"completionItem/resolve","params":{"data":{"cacheId":31},"filterText":".staticStatusText","kind":5,"label":"staticStatusText","sortText":"11","textEdit":{"newText":".staticStatusText","range":{"end":{"character":16,"line":12},"start":{"character":15,"line":12}}}},"id":7}
2025-09-24T21:46:40.754 helix_lsp::transport [INFO] tailwindcss-ls -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"import { Transaction } from '@shared/types/__generated_types__';\n\nimport { createColumnFactory } from '../../../shared-ui/table-columns';\n\nconst columnFactory = createColumnFactory<Transaction>();\n\nconst columns = [\n  columnFactory.customer('customer', { header: 'Customer' }),\n  columnFactory.amount('amount', { header: 'Amount' }),\n  columnFactory.text('transactionType.name', {\n    header: 'Transaction Type',\n  }),\n  columnFactory.('paymentMethodService'),\n  columnFactory.statusByValue('transactionStatus.slug', {\n    header: 'Status',\n  }),\n  columnFactory.date('createdAt', { header: 'Date' }),\n];\n\nexport default columns;\n"}],"textDocument":{"uri":"file:///file/path/users-table/columns.tsx","version":11}}}
2025-09-24T21:46:40.754 helix_lsp::transport [INFO] emmet-ls -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":22,"line":12},"start":{"character":15,"line":12}},"text":"."}],"textDocument":{"uri":"file:///file/path/users-table/columns.tsx","version":11}}}
2025-09-24T21:46:41.260 helix_lsp::transport [INFO] tailwindcss-ls <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///file/path/users-table/columns.tsx","diagnostics":[]}}
2025-09-24T21:46:53.631 helix_lsp::transport [INFO] vscode-eslint-language-server <- {"jsonrpc":"2.0","method":"eslint/status","params":{"uri":"file:///file/path/users-table/columns.tsx","state":1}}
2025-09-24T21:46:57.917 helix_lsp::transport [INFO] typescript-language-server <- {"jsonrpc":"2.0","id":6,"result":{"data":{"file":"/file/path/users-table/columns.tsx","line":13,"offset":17,"entryNames":["staticStatusText"]},"filterText":".staticStatusText","kind":5,"label":"staticStatusText","sortText":"11","textEdit":{"newText":".staticStatusText","range":{"end":{"character":16,"line":12},"start":{"character":15,"line":12}}},"detail":"(property) staticStatusText: (accessor: AccessorEntity<Transaction>, config: StatusColumnConfig) => ColumnDef<Transaction, unknown>","documentation":{"kind":"markdown","value":"Status column using Status component"}}}
2025-09-24T21:47:00.757 helix_term::ui::completion [ERROR] Failed to resolve completion item: request 7 timed out
2025-09-24T21:47:00.757 helix_lsp::transport [INFO] typescript-language-server -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":16,"line":12},"start":{"character":15,"line":12}},"text":".staticStatusText"}],"textDocument":{"uri":"file:///file/path/users-table/columns.tsx","version":12}}}

From the logs above, when the LSP hangs, it resorts to the following error from helix, based on my analysis (id 7)

2025-09-24T21:47:00.757 helix_term::ui::completion [ERROR] Failed to resolve completion item: request 7 timed out

Autocomplete example

  1. type staticSta
  2. selectstaticStatusText
  3. hit the enter key.
// file/path/users-table/columns.tsx
...
import { createColumnFactory } from '../../../shared-ui/table-columns';

const columnFactory = createColumnFactory<Transaction>();

const columns = [~
...
  columnFactory.statusByValue('transactionStatus.slug', {
    header: 'Status',
  }),
  columnFactory.date('createdAt', { header: 'Date' }),
...
];

export default columns;

This problem is slowing me down so much. Any solution this will be highly appreciated.
Thanks.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions