microsoft/typescript-go · error · Error

Language client is not initialized

Error message

Language client is not initialized

What it means

`Client.initializeAPISession` in _extension/src/client.ts lets other extensions get a direct pipe to the language server by sending the LSP request `custom/initializeAPISession`. The underlying vscode-languageclient `LanguageClient` is only constructed inside `Client.start()` (client.ts:205) and is torn down on stop, so calling this API before the session has started (or after it stopped) finds `this.client` undefined and throws this localized error.

Source

Thrown at _extension/src/client.ts:312

        await Promise.all(disposables.map(d => d.dispose()));
        await this.client?.dispose();
    }

    getCurrentExe(): { path: string; version: string; } | undefined {
        return this.exe;
    }

    get serverPid(): number | undefined {
        return (this.client as any)?._serverProcess?.pid;
    }

    /**
     * Initialize an API session and return the socket path for connecting.
     * This allows other extensions to get a direct connection to the API server.
     */
    async initializeAPISession(pipe?: string): Promise<{ sessionId: string; pipe: string; }> {
        if (!this.client) {
            throw new Error(vscode.l10n.t("Language client is not initialized"));
        }
        return this.client.sendRequest<{ sessionId: string; pipe: string; }>("custom/initializeAPISession", { pipe });
    }

    /**
     * Restart the language server if the executable path has not changed.
     * Returns true if a restart was performed.
     */
    async tryRestart(context: vscode.ExtensionContext): Promise<boolean> {
        if (!this.client) {
            return Promise.reject(new Error(vscode.l10n.t("Language client is not initialized")));
        }
        this.isStopping = false;
        const exe = await getExe(context);
        if (exe.path !== this.exe?.path) {
            return false;
        }

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Wait for readiness before calling: await the extension's activation completion and its initialized event / check the session's `isInitialized` state (client.ts:53)
  2. Wrap the call in try/catch and retry once after the initialized event fires, since startup is transient
  3. If it persists, check the TypeScript Native Preview output channel — the server may have failed to start (missing exe, crash), which leaves the client uninitialized

Example fix

// before
const session = await tsNativePreview.initializeAPISession(); // throws during startup race

// after
await tsNativePreview.waitForInitialization?.() ?? waitUntil(() => tsNativePreview.isInitialized);
const session = await tsNativePreview.initializeAPISession();
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling the API, confirm the session is up
const ext = vscode.extensions.getExtension("typescript-native-preview")!;
await ext.activate();
if (!ext.exports?.isInitialized) {
  // wait for the extension's initialized event or poll isInitialized before calling
  await waitFor(() => ext.exports?.isInitialized === true, timeoutMs);
}

Type guard

interface APISessionProvider {
  isInitialized: boolean;
  initializeAPISession(pipe?: string): Promise<{ sessionId: string; pipe: string }>;
}
function isReadySessionProvider(api: unknown): api is APISessionProvider {
  return !!api && typeof (api as APISessionProvider).initializeAPISession === "function"
    && (api as APISessionProvider).isInitialized === true;
}

Try / catch

try {
  const session = await api.initializeAPISession();
} catch (e) {
  if (e instanceof Error && /not initialized/i.test(e.message)) {
    // transient startup race: wait for the initialized event, retry once
    await onSessionInitialized();
    const session = await api.initializeAPISession();
  } else {
    throw e; // real failure — surface it (check the output channel for server crashes)
  }
}

Prevention

When it happens

Trigger: Another extension calls `initializeAPISession()` during VS Code startup before the TypeScript Native Preview extension finished activation (exe download/launch), or after the session was stopped/restarted (e.g. user disabled it, or a config change triggered restart). The same guard also protects `tryRestart`.

Common situations: Extension-activation races — the consuming extension activates faster than the language server session; calling the exported API in tests without starting the client; the server crashed/stopped and the API is invoked while `client` is unset.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/c636f4ffa992e86a. Report an issue: GitHub.