can1357/oh-my-pi · error

LSP server ${config.command} failed to initialize recently:

Error message

LSP server ${config.command} failed to initialize recently: ${recentFailure.message}

What it means

The client tracks deterministic initialization failures per server key with a backoff window (INIT_FAILURE_BACKOFF_MS). If the server failed to initialize recently, the library refuses to respawn it immediately — respawning a broken server on every tool call wastes the full init timeout each time — and throws with the original failure message.

Source

Thrown at packages/coding-agent/src/lsp/client.ts:992

		}
		const clientAfterReload = clients.get(key);
		if (clientAfterReload && !invalidatedClientKeys.has(key)) {
			clientAfterReload.lastActivity = Date.now();
			return clientAfterReload;
		}
		const lockAfterReload = clientLocks.get(key);
		if (lockAfterReload) return lockAfterReload.promise;
		if (invalidatedClientKeys.has(key)) {
			throw new Error(`LSP configuration was superseded during reload: ${config.command}`);
		}
	}

	// Fail fast on a recent deterministic init failure instead of re-spawning
	// a broken server (and paying its full init wait) on every call.
	const recentFailure = initFailures.get(key);
	if (recentFailure) {
		if (Date.now() - recentFailure.at < INIT_FAILURE_BACKOFF_MS) {
			throw new Error(`LSP server ${config.command} failed to initialize recently: ${recentFailure.message}`);
		}
		initFailures.delete(key);
	}

	// Create new client with lock
	const lockToken = Symbol();
	const clientPromise = (async () => {
		const baseCommand = config.resolvedCommand ?? config.command;
		const baseArgs = config.args ?? [];

		// Wrap with lspmux if available and supported
		const { command, args, env } = isLspmuxSupported(baseCommand)
			? await getLspmuxCommand(baseCommand, baseArgs)
			: { command: baseCommand, args: baseArgs };

		// Prefer the broker-shared server unless an external lspmux wrapper is
		// already multiplexing this command. Any shared-path failure falls back
		// to a private spawn so LSP never regresses on broker trouble.

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the root cause reported in the message (install the server binary, fix the project)
  2. Wait out the backoff window (INIT_FAILURE_BACKOFF_MS) and retry
  3. Explicitly reset/reload LSP config to clear the failure cache

Example fix

// before: immediate retry loop against dead server
for (;;) await lspDiagnostics(file);
// after: back off and surface root cause
try { await lspDiagnostics(file); }
catch (e) { logger.warn(e.message); await Bun.sleep(BACKOFF_MS); }
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the server command is runnable before invoking LSP
const bin = $which(config.command);
if (!bin) throw new Error(`LSP command not on PATH: ${config.command}`);

Try / catch

try {
  const client = await getConfigOrCreate(config, cwd);
} catch (err) {
  if (err.message.startsWith(`LSP server ${config.command} failed to initialize recently`)) {
    // Surface the root cause to the user instead of hammering the dead server
    logger.warn('LSP init failing repeatedly', { command: config.command, cause: err.message });
  }
  throw err;
}

Prevention

When it happens

Trigger: An earlier attempt to start the LSP server failed (crash, bad command, timeout), and a new LSP-dependent call arrives within the backoff window.

Common situations: LSP binary not installed or not on PATH; server crashes on startup due to bad project state; server requires a newer runtime version than installed.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1cde13b3d0906a49. Report an issue: GitHub.