{"record":{"id":"43fa883d0b1eb779","repo":"alibaba/open-code-review","slug":"s-produced-more-than-64kib-of-output","errorCode":null,"errorMessage":"%s produced more than 64KiB of output","messagePattern":"(.+?) produced more than 64KiB of output","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/llm/keycmd.go","lineNumber":92,"sourceCode":"\t// pipe closed. exec.CommandContext SIGKILLs only the shell, so a grandchild\n\t// (gpg-agent, pinentry, `op`) that inherited the stdout pipe keeps it open\n\t// and Wait blocks on the read long past the timeout -- reproducible with\n\t// api_key_cmd = \"sleep 200 & printf tok\". WaitDelay makes Wait give up\n\t// shortly after the context dies.\n\tout := &cappedBuffer{max: keyCmdMaxOutput}\n\tc.Stdout = out\n\tc.WaitDelay = keyCmdWaitDelay\n\n\terr := c.Run()\n\t// Checked first so a timeout reports as such instead of as the SIGKILL exit\n\t// status it produces. (Run has already joined every stdout copier, so the\n\t// buffer below is safe to read on all paths.)\n\tif ctx.Err() == context.DeadlineExceeded {\n\t\t// Wrap ctx.Err() so callers can errors.Is(err, context.DeadlineExceeded).\n\t\treturn \"\", fmt.Errorf(\"%s timed out after %s: %w\", label, keyCmdTimeout, ctx.Err())\n\t}\n\tif out.overflow {\n\t\treturn \"\", fmt.Errorf(\"%s produced more than 64KiB of output\", label)\n\t}\n\t// ErrWaitDelay only means an orphaned grandchild still holds the pipe; the\n\t// command itself exited fine and its output is already buffered, so use it\n\t// rather than surfacing an exec-internal error.\n\tif err != nil && !errors.Is(err, exec.ErrWaitDelay) {\n\t\t// Covers non-zero exit and command-not-found (the shell exits non-zero\n\t\t// and prints its not-found message on the child's stderr). ExitError.Stderr\n\t\t// stays nil because we assigned c.Stderr, so no output can leak here.\n\t\treturn \"\", fmt.Errorf(\"%s failed: %w\", label, err)\n\t}\n\n\t// Trim a trailing line break; multi-line output past that is ambiguous and refused.\n\t// ContainsAny (not Contains \"\\n\") so a lone interior CR is caught too: TrimRight\n\t// leaves it, TrimSpace below only strips the edges, and a CR inside a credential\n\t// makes net/http reject the Authorization header with an opaque error.\n\ttrimmed := strings.TrimRight(out.buf.String(), \"\\r\\n\")\n\tif strings.ContainsAny(trimmed, \"\\n\\r\") {\n\t\treturn \"\", fmt.Errorf(\"%s produced multi-line output; expected a single credential (pipe through 'head -n1' if your command prints more)\", label)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/llm/keycmd.go#L74-L110","documentation":"The credential command's captured stdout is capped at 64KiB. When out.overflow is set, the output is oversized and untrustworthy, so resolveKeyCmd refuses it with this error instead of returning a corrupted or truncated key.","triggerScenarios":"The configured key command prints far more than the key — a script that also dumps debug output to stdout, a CLI printing a full JSON document plus banners, or a loop accidentally emitting data continuously.","commonSituations":"Helper scripts echoing credentials plus verbose logs; a command streaming progress to stdout instead of stderr; fetching a token bundle when a single key is expected.","solutions":["Make the command print only the credential to stdout (move logs to stderr)","Extract the exact field in the shell, e.g. jq -r '.token' or --query ... --output text","Fix accidental infinite output loops in the helper script","Verify with: <your-cmd> | wc -c — output must be well under 64KiB"],"exampleFix":"// before\nkeyCmd: \"aws codeartifact get-authorization-token --output json\"\n// after\nkeyCmd: \"aws codeartifact get-authorization-token --output text --query authorizationToken\"","handlingStrategy":"validation","validationCode":"out, _ := exec.Command(\"sh\", \"-c\", \"<your-key-cmd>\").Output()\nif len(out) > 60000 { /* oversized; fix the command before use */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Print only the credential on stdout; send logs to stderr","Extract exact fields with jq / --query rather than dumping JSON","Avoid helper scripts with loops or verbose stdout output"],"tags":["exec","credentials","output-limit"],"backgroundTag":"command-output-overflow","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}