alibaba/open-code-review · error

%s failed: %w

Error message

%s failed: %w

What it means

If the key command exits non-zero or cannot be executed, the failure is reported as `<label> failed: %w` wrapping the exec error. This covers non-zero exit codes and command-not-found (the shell exits non-zero and prints its message on the child's stderr). exec.ErrWaitDelay is deliberately excluded, since it only means an orphaned grandchild holds the pipe while the output is already valid.

Source

Thrown at internal/llm/keycmd.go:101

	err := c.Run()
	// Checked first so a timeout reports as such instead of as the SIGKILL exit
	// status it produces. (Run has already joined every stdout copier, so the
	// buffer below is safe to read on all paths.)
	if ctx.Err() == context.DeadlineExceeded {
		// Wrap ctx.Err() so callers can errors.Is(err, context.DeadlineExceeded).
		return "", fmt.Errorf("%s timed out after %s: %w", label, keyCmdTimeout, ctx.Err())
	}
	if out.overflow {
		return "", fmt.Errorf("%s produced more than 64KiB of output", label)
	}
	// ErrWaitDelay only means an orphaned grandchild still holds the pipe; the
	// command itself exited fine and its output is already buffered, so use it
	// rather than surfacing an exec-internal error.
	if err != nil && !errors.Is(err, exec.ErrWaitDelay) {
		// Covers non-zero exit and command-not-found (the shell exits non-zero
		// and prints its not-found message on the child's stderr). ExitError.Stderr
		// stays nil because we assigned c.Stderr, so no output can leak here.
		return "", fmt.Errorf("%s failed: %w", label, err)
	}

	// Trim a trailing line break; multi-line output past that is ambiguous and refused.
	// ContainsAny (not Contains "\n") so a lone interior CR is caught too: TrimRight
	// leaves it, TrimSpace below only strips the edges, and a CR inside a credential
	// makes net/http reject the Authorization header with an opaque error.
	trimmed := strings.TrimRight(out.buf.String(), "\r\n")
	if strings.ContainsAny(trimmed, "\n\r") {
		return "", fmt.Errorf("%s produced multi-line output; expected a single credential (pipe through 'head -n1' if your command prints more)", label)
	}
	// Same reason as the line-break check, wider net: httpguts.ValidHeaderFieldValue
	// (what net/http enforces) rejects every byte below 0x20 except SP and TAB, plus
	// DEL. A NUL or VT smuggled in by e.g. `printf 'sk-a\0b'` would otherwise reach
	// net/http as the opaque `invalid header field value for "Authorization"`.
	//
	// Deliberately before the TrimSpace below, so a trailing control byte is an
	// error naming its offset rather than silently stripped: only TAB, SP and the
	// line breaks already handled above are things a credential command can

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Run the command manually with the same user/environment and check its exit code and stderr
  2. Fix the underlying helper failure (credentials, config, permissions)
  3. Correct the command name/path — ensure the binary is in PATH or use an absolute path
  4. Inspect the wrapped exec.ExitError for the exit code; check the shell's stderr

Example fix

// before
keyCmd: "op read op://vault/item/cred" // op not installed on CI
// after
keyCmd: "/usr/local/bin/op read op://vault/item/cred" // installed, absolute path
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := exec.LookPath("<your-key-cmd-binary>"); err != nil { /* not in PATH; install or use an absolute path */ }

Try / catch

key, err := resolveKeyCmd(ctx, cfg)
if err != nil {
	var exitErr *exec.ExitError
	if errors.As(err, &exitErr) {
		log.Printf("helper exited %d; check its auth/config", exitErr.ExitCode())
	}
	return err
}

Prevention

When it happens

Trigger: The configured credential command exits non-zero — wrong password, missing binary in PATH, denied permissions, or the command name does not exist.

Common situations: Typo in the command path; helper not installed in the environment the tool runs in (cron/CI PATH differs); secrets CLI failing auth; script erroring on a missing config file.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/efdc744900536ee6. Report an issue: GitHub.