microsoft/TypeScript · error · Error

LanguageService Operation: ${key} not allowed in LanguageSer

Error message

LanguageService Operation: ${key} not allowed in LanguageServiceMode.Syntactic

What it means

Thrown by a LanguageService created in LanguageServiceMode.Syntactic when you call an operation that needs type/semantic information. Syntactic mode (also reachable by passing the legacy boolean true as the third argument to createLanguageService) disables everything in invalidOperationsInSyntacticMode: the entire PartialSemantic list plus getCompletionsAtPosition, getCompletionEntryDetails, getCompletionEntrySymbol, getSignatureHelpItems, getQuickInfoAtPosition, getDefinitionAtPosition, getDefinitionAndBoundSpan, getImplementationAtPosition, getTypeDefinitionAtPosition, getReferencesAtPosition, findReferences, getDocumentHighlights, getNavigateToItems, getRenameInfo, findRenameLocations, getApplicableRefactors, and preparePasteEditsForFile. The most restrictive of the three modes, it parses only — no bound program, no type resolution — so any type-dependent call is replaced with a throwing thunk.

Source

Thrown at src/services/services.ts:3471

        preparePasteEditsForFile,
        getPasteEdits,
        mapCode,
    };

    switch (languageServiceMode) {
        case LanguageServiceMode.Semantic:
            break;
        case LanguageServiceMode.PartialSemantic:
            invalidOperationsInPartialSemanticMode.forEach(key =>
                ls[key] = () => {
                    throw new Error(`LanguageService Operation: ${key} not allowed in LanguageServiceMode.PartialSemantic`);
                }
            );
            break;
        case LanguageServiceMode.Syntactic:
            invalidOperationsInSyntacticMode.forEach(key =>
                ls[key] = () => {
                    throw new Error(`LanguageService Operation: ${key} not allowed in LanguageServiceMode.Syntactic`);
                }
            );
            break;
        default:
            Debug.assertNever(languageServiceMode);
    }
    return ls;
}

/**
 * Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`.
 *
 * @internal
 */
export function getNameTable(sourceFile: SourceFile): Map<__String, number> {
    if (!sourceFile.nameTable) {
        initializeNameTable(sourceFile);
    }

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Create the LanguageService in Semantic mode: pass undefined (the default) or ts.LanguageServiceMode.Semantic as the third argument, instead of true or ts.LanguageServiceMode.Syntactic.
  2. If using the boolean overload, ensure you pass false (not true) when you want full semantic features.
  3. Maintain separate services: a Syntactic one for outliningSpans/braceMatching/formatting and a Semantic one for completions, quickinfo, definitions, references, rename.
  4. Gate every IntelliSense/diagnostics call behind a check that the service was created in Semantic mode before dispatching.

Example fix

// before (legacy boolean overload: true => Syntactic)
const ls = ts.createLanguageService(host, registry, true);
ls.getQuickInfoAtPosition(file, 0); // throws

// after
const ls = ts.createLanguageService(host, registry, ts.LanguageServiceMode.Semantic);
ls.getQuickInfoAtPosition(file, 0);
Defensive patterns

Strategy: validation

Validate before calling

// Avoid the legacy boolean overload ambiguity: be explicit.
const mode = ts.LanguageServiceMode.Semantic; // pass undefined for the same default
const ls = ts.createLanguageService(host, registry, mode);

Type guard

// Everything blocked in Syntactic mode (services.ts:1607) =
// invalidOperationsInPartialSemanticMode + the syntactic-only additions.
const SYNTACTIC_BLOCKED = new Set([
  "getSemanticDiagnostics","getSuggestionDiagnostics","getCompilerOptionsDiagnostics",
  "getSemanticClassifications","getEncodedSemanticClassifications",
  "getCodeFixesAtPosition","getCombinedCodeFix","applyCodeActionCommand",
  "organizeImports","getEditsForFileRename","getEmitOutput","getApplicableRefactors",
  "getEditsForRefactor","prepareCallHierarchy","provideCallHierarchyIncomingCalls",
  "provideCallHierarchyOutgoingCalls","provideInlayHints","getSupportedCodeFixes","getPasteEdits",
  "getCompletionsAtPosition","getCompletionEntryDetails","getCompletionEntrySymbol",
  "getSignatureHelpItems","getQuickInfoAtPosition","getDefinitionAtPosition",
  "getDefinitionAndBoundSpan","getImplementationAtPosition","getTypeDefinitionAtPosition",
  "getReferencesAtPosition","findReferences","getDocumentHighlights",
  "getNavigateToItems","getRenameInfo","findRenameLocations","preparePasteEditsForFile",
] as const);
function isAllowedInSyntactic(op: string): boolean {
  return !SYNTACTIC_BLOCKED.has(op as any);
}

Try / catch

// Discouraged: catch only as a last resort. The real fix is using Semantic mode.
try {
  ls.getQuickInfoAtPosition(file, offset);
} catch (e) {
  if (e instanceof Error && /not allowed in LanguageServiceMode\.Syntactic/.test(e.message)) {
    // fall back to a Semantic-mode LanguageService for this request
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createLanguageService(host, registry, ts.LanguageServiceMode.Syntactic) — or the boolean form createLanguageService(host, registry, true) — then invoking a type-dependent method such as ls.getQuickInfoAtPosition(...), ls.getCompletionsAtPosition(...), ls.getDefinitionAtPosition(...), ls.findRenameLocations(...), or any of the PartialSemantic-listed operations like getSemanticDiagnostics. The interpolated key names the exact method invoked.

Common situations: Passing the legacy boolean third arg `true` (which silently maps to Syntactic) instead of undefined/Semantic, expecting full IntelliSense. Using a syntax-only LanguageService (e.g. for fast formatting/outline) but then wiring it up to hover/go-to-definition/completion handlers. Upgrading hosts that previously always created a Semantic service to a configurable mode without updating call sites.

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/82a3620cef5d3452. Report an issue: GitHub.