{"record":{"id":"e9bbc7d42a5606a1","repo":"mastra-ai/mastra","slug":"failed-to-create-lsp-process-with-proper-stdio","errorCode":null,"errorMessage":"Failed to create LSP process with proper stdio","messagePattern":"Failed to create LSP process with proper stdio","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/lsp/client.ts","lineNumber":44,"sourceCode":"   */\n  async initialize(): Promise<void> {\n    const spawnResult = await this.serverInfo.spawn(this.workspaceRoot);\n\n    if (!spawnResult) {\n      throw new Error('Failed to spawn LSP server');\n    }\n\n    // Handle both ChildProcess and { process: ChildProcess, initialization? } formats\n    let initializationOptions: any = undefined;\n    if ('process' in spawnResult) {\n      this.process = spawnResult.process;\n      initializationOptions = spawnResult.initialization;\n    } else {\n      this.process = spawnResult;\n    }\n\n    if (!this.process.stdin || !this.process.stdout) {\n      throw new Error('Failed to create LSP process with proper stdio');\n    }\n\n    const reader = new StreamMessageReader(this.process.stdout);\n    const writer = new StreamMessageWriter(this.process.stdin);\n    this.connection = createMessageConnection(reader, writer);\n\n    // Handle connection errors (e.g., ERR_STREAM_DESTROYED during shutdown)\n    this.connection.onError(error => {\n      // Silently ignore stream destroyed errors during shutdown\n      const errorObj = error?.[0] as any;\n      if (errorObj?.code !== 'ERR_STREAM_DESTROYED') {\n      }\n    });\n\n    // Set up diagnostic listener before starting connection\n\n    this.connection.onNotification('textDocument/publishDiagnostics', (params: any) => {\n      if (params.diagnostics && params.diagnostics.length > 0) {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/lsp/client.ts#L26-L62","documentation":"After spawning, the LSP client requires the child process to expose both stdin and stdout for the JSON-RPC stream connection. If either stream is missing (null), initialize() throws 'Failed to create LSP process with proper stdio'. Without these streams, createMessageConnection cannot be built, so the client fails fast.","triggerScenarios":"serverInfo.spawn returned a process-like object whose stdin/stdout are null — e.g. spawn created with stdio: 'ignore' or piped incorrectly, a custom spawn implementation returning an object without proper stdio streams, or the process exited immediately destroying streams before the check.","commonSituations":"Custom LSPServerInfo implementations using stdio options other than 'pipe'/'jsonrpc' for stdin/stdout; a server wrapper that detaches stdio; spawn options like detached:true with stdio 'ignore'.","solutions":["Spawn the server with stdio configured to pipe stdin/stdout (e.g. stdio: ['pipe', 'pipe', 'pipe']).","If the spawn result shape is { process, initialization }, ensure `process` is the actual ChildProcess with working streams.","Add a pre-check in the spawn callback that returns the ChildProcess only when stdin/stdout are present.","Catch this error during initialize() and log the spawn args to identify the misconfigured stdio option."],"exampleFix":"// before\nspawn(command, args, { stdio: 'ignore' }); // stdin/stdout null\n// after\nspawn(command, args, { stdio: ['pipe', 'pipe', 'pipe'] });","handlingStrategy":"validation","validationCode":"import type { ChildProcess } from 'node:child_process';\nfunction hasValidStdio(p: ChildProcess | null | undefined): p is ChildProcess & { stdin: NonNullable<ChildProcess['stdin']>; stdout: NonNullable<ChildProcess['stdout']> } {\n  return !!p && p.stdin != null && p.stdout != null;\n}\n// validate the result of spawn before handing it to LSPClient","typeGuard":"function isSpawnableProcess(p: unknown): p is ChildProcess & { stdin: NodeJS.WritableStream; stdout: NodeJS.ReadableStream } {\n  const c = p as ChildProcess | undefined;\n  return !!c && typeof c.pid === 'number' && c.stdin != null && c.stdout != null;\n}","tryCatchPattern":"try {\n  await client.initialize();\n} catch (e) {\n  if (e.message === 'Failed to create LSP process with proper stdio') {\n    throw new Error(`LSP server '${serverInfo.command}' must be spawned with piped stdin/stdout (stdio: 'pipe')`);\n  }\n  throw e;\n}","preventionTips":["Always spawn LSP servers with stdio pipes for stdin/stdout ('pipe' or 'jsonrpc').","In custom spawn implementations, return the ChildProcess only after confirming stdin/stdout exist.","Avoid detached/ignore stdio modes for LSP server processes."],"tags":["lsp","stdio","process"],"backgroundTag":"lsp-server-spawn-failure","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}