{"record":{"id":"dc8747d2c32613ab","repo":"gastownhall/beads","slug":"w-s-dc8747","errorCode":null,"errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/creds/command.go","lineNumber":97,"sourceCode":"\tcredCache   = map[string]cachedCred{}\n\n\t// credRunner runs the helper; a package var so tests can stub it without a shell.\n\tcredRunner = func(ctx context.Context, command string) ([]byte, error) {\n\t\t// POSIX shells parse the helper command; native Windows has no `sh`, so\n\t\t// dispatch through cmd.exe there so a bare Windows bd does not hard-fail\n\t\t// every *_PASSWORD_COMMAND / CREDENTIAL_COMMAND in the fail-closed ladder.\n\t\tvar cmd *exec.Cmd\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\tcmd = exec.CommandContext(ctx, \"cmd.exe\", \"/C\", command)\n\t\t} else {\n\t\t\tcmd = exec.CommandContext(ctx, \"sh\", \"-c\", command)\n\t\t}\n\t\tvar stdout, stderr bytes.Buffer\n\t\tcmd.Stdout = &stdout\n\t\tcmd.Stderr = &stderr\n\t\tif err := cmd.Run(); err != nil {\n\t\t\tif msg := strings.TrimSpace(stderr.String()); msg != \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"%w: %s\", err, msg)\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\treturn stdout.Bytes(), nil\n\t}\n)\n\n// resolveCredentialToken returns the token (and any username/expiry) for the given\n// helper command, using a process-level cache keyed by the command so repeated opens\n// don't re-spawn the helper until the token is near expiry. It is concurrency-safe.\nfunc resolveCredentialToken(ctx context.Context, command string) (token, username string, expiry time.Time, err error) {\n\tnow := time.Now()\n\n\tcredCacheMu.Lock()\n\tif c, ok := credCache[command]; ok && now.Before(c.expires.Add(-credExpirySkew)) {\n\t\ttok, user, exp := c.token, c.username, c.expires\n\t\tcredCacheMu.Unlock()\n\t\treturn tok, user, exp, nil","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/creds/command.go#L79-L115","documentation":"The credential helper runner executes an external credential command and, when it exits non-zero, wraps the exec error with the helper's captured stderr. This gives the developer both the OS-level failure and the helper's own diagnostic message in one error chain.","triggerScenarios":"The configured credential command (e.g. a gh/docker credential helper script) exits non-zero after printing a message to stderr; cmd.Run returns an *exec.ExitError and stderr is non-empty.","commonSituations":"Credential helper not authenticated (expired OAuth token), helper script crashing with its own error message, helper refusing to serve credentials for the requested host, PATH pointing at an old/broken helper binary.","solutions":["Read the trailing text after the colon — it is the helper's stderr and usually states the real cause (e.g. 'gh auth: not logged in').","Re-authenticate with the helper (e.g. `gh auth login`, `docker login`).","Run the credential command manually with the same arguments to reproduce and debug its stderr.","Verify the helper binary version on PATH is current."],"exampleFix":"// before\n// error: exit status 1: gh auth token: not logged in\n// after\n$ gh auth login   # then retry the credential resolution","handlingStrategy":"try-catch","validationCode":"cmd := exec.Command(helper, args...)\nif _, err := exec.LookPath(helper); err != nil {\n    // helper missing; fix config before relying on it\n}","typeGuard":null,"tryCatchPattern":"cred, err := creds.Resolve(ctx)\nif err != nil {\n    var ee *exec.ExitError\n    if errors.As(err, &ee) {\n        // stderr text after the colon is the helper's own message\n    }\n    return fmt.Errorf(\"credential resolution failed: %w\", err)\n}","preventionTips":["Keep credential helpers installed, on PATH, and authenticated (`gh auth status`).","Pin helper binary versions and update them deliberately.","Test the helper command manually with the same arguments bd uses."],"tags":["credentials","exec","external-command"],"backgroundTag":"credential-helper-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}