Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 10, 2025

  • Understand the issue: crash in getArgumentArityError when maxCount >= len(args)
  • Identify root cause: accessing args[maxCount] without bounds check in the default branch
  • Update test to use minimal repro with correct marker position and trigger kind
  • Verify test reproduces the crash without the fix
  • Implement the fix in checker.go - add bounds check before accessing args[maxCount]
  • Verify the fix works and all tests pass
  • Run linting and formatting
Original prompt

This section details on the original issue you should resolve

<issue_title>Signature help crash on call target when nested call has trailing comma</issue_title>
<issue_description>Had a hard time coming up with a minimal repro but here's the actual code it was found in.

https://github.com/microsoft/TypeScript/blob/1da8266179589bbc977ccbd8712614ed5ddd3004/src/services/navigationBar.ts#L681-L690

factory.createClassDeclaration/**/(

If you request signature help at the marker very quickly, you can trigger the following crash. This is tricky because it doesn't always happen. One way to often accomplish this in VS Code is to

  1. Trigger signature help (Ctrl+Shift+Space or just type , and delete it)
  2. Insert a stray character at the marker
  3. Immediately delete that stray character
error] panic handling requesttextDocument/signatureHelpruntime error: index out of range [5] with length 5goroutine 52857 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:26 +0x5e
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0xc0001e4008, 0xc047ef9620)
	github.com/microsoft/typescript-go/internal/lsp/server.go:701 +0x58
panic({0xca4c60?, 0xc039fbedb0?})
	runtime/panic.go:783 +0x132
github.com/microsoft/typescript-go/internal/checker.(*Checker).getArgumentArityError(0xc04bddf308, 0xc04b108088, {0xc04bda8cc8, 0x1, 0xc001964c58?}, {0xc0544361a8, 0x5, 0x5?}, 0x0)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9652 +0xa96
github.com/microsoft/typescript-go/internal/checker.(*Checker).reportCallResolutionErrors(0xc04bddf308, 0x109c2c0?, 0xc001964cf0, {0xc04bda8cc8, 0x1, 0x1}, 0x0)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9540 +0x1f2
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveCall(0xc04bddf308, 0xc04b108088, {0xc04bda8cc8, 0x1, 0x1}, 0x0, 0x1f, 0x0, 0x0)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8778 +0x605
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveCallExpression(0xc04bddf308, 0xc04b108088, 0x0, 0x1f)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8405 +0x62d
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveSignature(0xc04bddfa60?, 0x109c2c0?, 0xc04b108088?, 0x85688e?)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8292 +0x46
github.com/microsoft/typescript-go/internal/checker.(*Checker).getResolvedSignature(0xc04bddf308, 0xc04b108088, 0x0, 0x1f)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8264 +0xd8
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkCallExpression(0xc04bddf308, 0xc04b108088, 0x1f)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8160 +0x4f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionWorker(0xc04bddf308, 0xc04b108088, 0x1f)
	github.com/microsoft/typescript-go/internal/checker/checker.go:7546 +0x2df
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionEx(0xc04bddf308, 0xc04b108088, 0x1f)
	github.com/microsoft/typescript-go/internal/checker/checker.go:7334 +0x52
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionWithContextualType(0xc04bddf308, 0xc04bdac900?, 0xc04cf1a770, 0xc04bdac700, 0x1c)
	github.com/microsoft/typescript-go/internal/checker/checker.go:7261 +0x22c
github.com/microsoft/typescript-go/internal/checker.(*Checker).inferTypeArguments(0xc04bddf308, 0xc04b1080e0, 0xc01cdfa100, {0xc0544361d0, 0x2, 0x2}, 0x1c, 0xc04bdac700)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9345 +0x41e
github.com/microsoft/typescript-go/internal/checker.(*Checker).inferSignatureInstantiationForOverloadFailure(0xc04bddf308, 0xc04b1080e0, {0xc04bda8b48?, 0x3?, 0x781bb5?}, 0xc01cdfa100, {0xc0544361d0, 0x2, 0x2}, 0x10)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9437 +0x93
github.com/microsoft/typescript-go/internal/checker.(*Checker).pickLongestCandidateSignature(0xc04bddf308, 0xc04b1080e0, {0xc04bda8b58, 0x1, 0xc04bda8b58?}, {0xc0544361d0, 0x2, 0x2}, 0x10)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9395 +0x1d6
github.com/microsoft/typescript-go/internal/checker.(*Checker).getCandidateForOverloadFailure(0xc04bddf308, 0xc04b1080e0, {0xc04bda8b58, 0x1, 0x1}, {0xc0544361d0, 0x2, 0x2}, 0x1, 0x10)
	github.com/microsoft/typescript-go/internal/checker/checker.go:9365 +0xb4
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveCall(0xc04bddf308, 0xc04b1080e0, {0xc04bda8b50, 0x1, 0x1}, 0xc0019654f8, 0x10, 0x0, 0x0)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8758 +0x53d
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveCallExpression(0xc04bddf308, 0xc04b1080e0, 0xc0019654f8, 0x10)
	github.com/microsoft/typescript-go/internal/checker/checker.go:8405 +0x62d
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveSignature(0xc04bd...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes microsoft/typescript-go#2312

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

… comma

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix signature help crash on call target with trailing comma Fix signature help crash when nested call has trailing comma Dec 10, 2025
Copy link
Member

@DanielRosenwasser DanielRosenwasser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try again @copilot.

Comment on lines 21 to 29
outer(
inner(/*1*/
undefined,
undefined,
undefined,
undefined,
undefined,
),
);`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use the more minimal example from the repro.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that the example wasn't failing when you tried, but really, this is what I saw. The minimal repro was:

declare function outer<T>(range: T): T;
declare function inner(a: any): any;

outer(inner(undefined,),);

The LSP request was

{"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///example.ts"},"position":{"line":3,"character":11},"context":{"triggerKind":1,"isRetrigger":false}}}

The crash message for that example was

panic handling request textDocument/signatureHelp: runtime error: index out of range [1] with length 1

Make sure there is no TriggerCharacter, and also, this was an invoked trigger (so use SignatureHelpTriggerKindInvoked).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the test to use the minimal repro with the marker at inner/*1*/(undefined,) and SignatureHelpTriggerKindInvoked. The test now correctly reproduces the crash without the fix. (0d98c09)

Comment on lines 9651 to 9660
// Handle edge case where maxCount >= len(args)
// This can happen when signature resolution fails for reasons other than argument count,
// such as when trailing commas create OmittedExpressions that affect type inference.
if maxCount >= len(args) {
diagnostic := NewDiagnosticForNode(errorNode, message, parameterRange, len(args))
if headMessage != nil {
diagnostic = ast.NewDiagnosticChain(diagnostic, headMessage)
}
return diagnostic
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels wrong - the error is because there is a trailing comma. I don't think there is an omitted expression anywhere, so the arities seem right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment to clarify that the issue is due to trailing commas causing signature resolution to fail, not OmittedExpressions. The bounds check guards against maxCount >= len(args) which occurs when we reach this fallback error path but the argument count actually matches the parameter count. (0d98c09)

…imal repro

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 10, 2025

Try again @copilot.

Fixed the test to use the minimal repro with the correct marker position. The test now properly reproduces the crash (index out of range [1] with length 1) without the fix. (0d98c09)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants