{"record":{"id":"c331e731f6831d7b","repo":"github/copilot-sdk","slug":"failed-to-create-stdin-pipe-w","errorCode":null,"errorMessage":"failed to create stdin pipe: %w","messagePattern":"failed to create stdin pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/client.go","lineNumber":2171,"sourceCode":"\t\t\tc.process.Env = setEnvValue(c.process.Env, \"COPILOT_OTEL_EXPORTER_TYPE\", t.ExporterType)\n\t\t}\n\t\tif t.SourceName != \"\" {\n\t\t\tc.process.Env = setEnvValue(c.process.Env, \"COPILOT_OTEL_SOURCE_NAME\", t.SourceName)\n\t\t}\n\t\tif t.CaptureContent != nil {\n\t\t\tval := \"false\"\n\t\t\tif *t.CaptureContent {\n\t\t\t\tval = \"true\"\n\t\t\t}\n\t\t\tc.process.Env = setEnvValue(c.process.Env, \"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT\", val)\n\t\t}\n\t}\n\n\tif c.useStdio {\n\t\t// For stdio mode, we need stdin/stdout pipes\n\t\tstdin, err := c.process.StdinPipe()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create stdin pipe: %w\", err)\n\t\t}\n\n\t\tstdout, err := c.process.StdoutPipe()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create stdout pipe: %w\", err)\n\t\t}\n\n\t\tc.process.Stderr = truncbuffer.NewTruncBuffer(stderrBufferSize)\n\n\t\tif err := c.process.Start(); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to start CLI server: %w\", err)\n\t\t}\n\n\t\tc.monitorProcess()\n\n\t\t// Create JSON-RPC client immediately\n\t\tc.client = jsonrpc2.NewClient(stdin, stdout)\n\t\tc.client.SetProcessDone(c.processDone, c.processErrorPtr)","sourceCodeStart":2153,"sourceCodeEnd":2189,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/client.go#L2153-L2189","documentation":"In stdio mode Connect wraps the error from process.StdinPipe() with this message. The SDK could not obtain the stdin pipe to the CLI subprocess, so JSON-RPC communication cannot be set up. This typically reflects OS-level resource or process-state problems.","triggerScenarios":"Calling Connect() with useStdio enabled when os/exec cannot create the StdinPipe — e.g. process already started (StdinPipe called twice), or fd exhaustion.","commonSituations":"Calling Connect() twice on the same Client, running under a environment with a low file-descriptor limit (ulimit -n), or embedding the SDK in a sandboxed runtime that restricts pipes.","solutions":["Do not reuse a Client whose process already started; create a new Client and Connect once.","Check/increase the file descriptor limit (ulimit -n) in the runtime environment.","Log the wrapped underlying error (%w) to identify the exact OS failure.","Ensure the command path is correct so the exec.Cmd is in a valid pre-start state."],"exampleFix":"// before\nclient.Connect(ctx) // first connect\nclient.Connect(ctx) // second connect -> StdinPipe error\n\n// after\nif !client.IsConnected() {\n    if err := client.Connect(ctx); err != nil {\n        return fmt.Errorf(\"connect: %w\", err)\n    }\n}","handlingStrategy":"retry","validationCode":"// ensure fd headroom before connecting\nvar lim syscall.Rlimit\nsyscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)\nif lim.Cur < 256 { lim.Cur = 256; syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim) }","typeGuard":null,"tryCatchPattern":"if err := client.Connect(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to create stdin pipe\") {\n        client, err = sdk.NewClient(opts) // fresh process state\n        if err == nil { err = client.Connect(ctx) }\n    }\n    if err != nil { return err }\n}","preventionTips":["Connect exactly once per Client instance.","Raise ulimit -n in constrained environments.","Do not pre-start the exec.Cmd outside the SDK.","Log wrapped OS errors for diagnosis."],"tags":["go","stdio","process","pipe"],"backgroundTag":"broken-pipe","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}