{"record":{"id":"e8f2fce121159dad","repo":"github/copilot-sdk","slug":"failed-to-create-stdout-pipe-w","errorCode":null,"errorMessage":"failed to create stdout pipe: %w","messagePattern":"failed to create stdout pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/client.go","lineNumber":2176,"sourceCode":"\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)\n\t\tc.client.SetOnClose(c.handleConnectionClose)\n\t\tc.RPC = rpc.NewServerRPC(c.client)\n\t\tc.internalRPC = rpc.NewInternalServerRPC(c.client)\n\t\tc.setupNotificationHandler()\n\t\tc.client.Start()","sourceCodeStart":2158,"sourceCodeEnd":2194,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/client.go#L2158-L2194","documentation":"In stdio mode Connect wraps the error from process.StdoutPipe() with this message. The stdout pipe is required to read JSON-RPC responses from the CLI subprocess. Failure has the same root causes as the stdin pipe failure: wrong process state or OS resource limits.","triggerScenarios":"Connect() with useStdio enabled when StdoutPipe() fails — process already started (pipes can only be created before Start), or fd/resource exhaustion.","commonSituations":"Double Connect() on one Client, running in containers with tight fd limits, or a custom wrapper that started the process before calling Connect.","solutions":["Create a fresh Client per connection; never call Connect() after the process has started.","Raise the file descriptor limit if fd exhaustion is reported in the wrapped error.","Inspect the wrapped error for the precise OS reason.","Verify no other code path invoked process.Start() before Connect()."],"exampleFix":"// before\nprocess, _ := buildCmd()\nprocess.Start()\nclient.Connect(ctx) // StdoutPipe fails: process already started\n\n// after\nclient, _ := NewClient(WithCommand(buildCmd()))\nif err := client.Connect(ctx); err != nil {\n    return err\n}","handlingStrategy":"retry","validationCode":"// create pipes only on a fresh, unstarted process; guard with state flag\nif clientStarted { return errors.New(\"process already started; recreate client\") }","typeGuard":null,"tryCatchPattern":"if err := client.Connect(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to create stdout pipe\") {\n        client, err = sdk.NewClient(opts)\n        if err == nil { err = client.Connect(ctx) }\n    }\n    if err != nil { return err }\n}","preventionTips":["Never call Start() manually before Connect().","One Connect per Client; rebuild on failure.","Verify fd limits in containers.","Check process state before retrying."],"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"}