Skip to content

Keyword completion throws exception when typing in a new document #82221

@RikkiGibson

Description

@RikkiGibson

Repro:

  1. Open a blank file in VS Code. Save it as a C# file or set language mode to C#.
  2. Type 2-3 characters, like Con to use Console

Expected behavior: A filtered completion list is shown.

Actual behavior: An error popu appears, and a completion list is eventually shown which is missing many common items, which causes the editor to fight you really hard when typing normal C# code.
Image

An exception is thrown in the language server, see stack:

2026-01-29 20:37:08.381 [error] [textDocument/completion] [LanguageServerExtensionManager] Microsoft.CodeAnalysis.CSharp.Completion.Providers.KeywordCompletionProvider threw an exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'position')
   at Microsoft.CodeAnalysis.SyntaxNode.FindTokenCore(Int32 position, Boolean findInsideTrivia) in src\Compilers\Core\Portable\Syntax\SyntaxNode.cs:line 1458
   at Microsoft.CodeAnalysis.SyntaxNode.FindToken(Int32 position, Boolean findInsideTrivia) in src\Compilers\Core\Portable\Syntax\SyntaxNode.cs:line 1010
   at Microsoft.CodeAnalysis.Shared.Extensions.DocumentExtensions.ReuseExistingSpeculativeModelAsync(Document document, TextSpan span, CancellationToken cancellationToken) in src\Workspaces\SharedUtilitiesAndExtensions\Workspace\Core\Extensions\DocumentExtensions.cs:line 133
   at Microsoft.CodeAnalysis.Completion.Utilities.CreateSyntaxContextWithExistingSpeculativeModelAsync(Document document, Int32 position, CancellationToken cancellationToken) in src\Features\Core\Portable\Completion\Utilities.cs:line 55
   at Microsoft.CodeAnalysis.Threading.ProducerConsumer`1.<>c__DisplayClass11_0`3.<<RunParallelChannelAsync>b__2>d.MoveNext() in src\Dependencies\Threading\ProducerConsumer.cs:line 238
   at Microsoft.CodeAnalysis.Completion.Providers.AbstractKeywordCompletionProvider`1.RecommendCompletionItemsAsync(Document document, CompletionContext context, CancellationToken cancellationToken) in src\Features\Core\Portable\Completion\Providers\AbstractKeywordCompletionProvider.cs:line 48
   at System.Threading.Tasks.Parallel.<>c__57`1.<<ForEachAsync>b__57_0>d.MoveNext()
   at Microsoft.CodeAnalysis.Threading.ProducerConsumer`1.<>c__DisplayClass11_0`3.<<RunParallelChannelAsync>b__2>d.MoveNext() in src\Dependencies\Threading\ProducerConsumer.cs:line 238
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__57`1.<<ForEachAsync>b__57_0>d.MoveNext()
   at System.Threading.Tasks.Parallel.<>c__57`1.<<ForEachAsync>b__57_0>d.MoveNext()
   at Microsoft.CodeAnalysis.Shared.Extensions.DocumentExtensions.GetUnionItemsFromDocumentAndLinkedDocumentsAsync[T](Document document, IEqualityComparer`1 comparer, Func`2 getItemsWorker) in src\Features\Core\Portable\Shared\Extensions\DocumentExtensions.cs:line 64
   at Microsoft.CodeAnalysis.Completion.Providers.AbstractKeywordCompletionProvider`1.ProvideCompletionsAsync(CompletionContext context) in src\Features\Core\Portable\Completion\Providers\AbstractKeywordCompletionProvider.cs:line 39
   at Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformActionAsync(IExtensionManager extensionManager, Object extension, Func`1 function) in src\Workspaces\Core\Portable\ExtensionManager\IExtensionManagerExtensions.cs:line 58

It looks like this method is getting a syntax tree for an empty file (i.e. root.GetText().Length == 0), and then trying to get the token at position 1.

public static async ValueTask<SemanticModel> ReuseExistingSpeculativeModelAsync(this Document document, TextSpan span, CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(document.SupportsSemanticModel);
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(span.Start);
var node = token.Parent!.AncestorsAndSelf().First(a => a.FullSpan.Contains(span));

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions