{"record":{"id":"9028f8f979cfb4dd","repo":"gastownhall/beads","slug":"parse-gh-output-w","errorCode":null,"errorMessage":"parse gh output: %w","messagePattern":"parse gh output: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/gate.go","lineNumber":971,"sourceCode":"\t\t\"--workflow\", workflow,\n\t\t\"--json\", \"databaseId,name,status,conclusion,createdAt,workflowName\",\n\t\t\"--limit\", fmt.Sprintf(\"%d\", limit),\n\t}\n\tif repo != \"\" {\n\t\targs = append(args, \"--repo\", repo)\n\t}\n\n\toutput, stderr, err := runGH(args...)\n\tif err != nil {\n\t\tif len(stderr) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"gh run list --workflow=%s failed: %s\", workflow, string(stderr))\n\t\t}\n\t\treturn nil, fmt.Errorf(\"gh run list: %w\", err)\n\t}\n\n\tvar runs []GHWorkflowRun\n\tif err := json.Unmarshal(output, &runs); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse gh output: %w\", err)\n\t}\n\n\treturn runs, nil\n}\n\n// discoverRunIDByWorkflowName queries GitHub for the most recent run of a workflow.\n// Returns (runID, error). This is ZFC-compliant: \"most recent run\" is deterministic.\nfunc discoverRunIDByWorkflowName(workflowHint string) (string, error) {\n\treturn discoverRunIDByWorkflowNameInRepo(workflowHint, \"\")\n}\n\nfunc discoverRunIDByWorkflowNameInRepo(workflowHint, repo string) (string, error) {\n\treturn discoverRunIDByWorkflowNameInRepoWithRunner(workflowHint, repo, runGHCommand)\n}\n\n// discoverRunIDByWorkflowNameInRepoWithRunner is the runner-injectable form of\n// discoverRunIDByWorkflowNameInRepo. checkGHRunWithRunner's cross-repo branch\n// must call this (not discoverRunIDByWorkflowNameInRepo directly) so the same","sourceCodeStart":953,"sourceCodeEnd":989,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/gate.go#L953-L989","documentation":"After a successful `gh run list` invocation, its JSON output is unmarshaled into []GHWorkflowRun. If gh's output is not the expected JSON array (empty output, truncated output, human-readable output because --json was dropped/unsupported, or an old gh version with a different schema), this error wraps the json.Unmarshal failure.","triggerScenarios":"queryGitHubRunsForWorkflowInRepoWithRunner receives malformed/empty stdout from runGH — e.g. gh emitted a warning banner to stdout, a proxy returned HTML, output was truncated, or a fake runner returned non-JSON.","commonSituations":"Very old gh versions lacking the --json fields used; piping gh through text processors that altered output; capturing human-readable output (missing --json flag) in a custom runner; API degradation returning partial responses.","solutions":["Run `gh run list --workflow=<name> -R <repo> --json ...` manually and confirm valid JSON is printed (pipe to `jq .`).","Upgrade gh CLI to a recent version so the --json field set matches GHWorkflowRun.","If a custom ghCommandRunner is injected, ensure it returns raw gh stdout unmodified (no banners, no reformatting).","Add logging around output length/content to spot truncation or proxy-injected HTML, then fix the transport (proxy, pager: set GH_PAGER= / --no-pager)."],"exampleFix":"// before (fake runner returning human output)\nreturn []byte(\" Showing 2 of 2 runs\"), nil, nil\n// after\nreturn []byte(`[{\"databaseId\":123,\"status\":\"completed\",\"conclusion\":\"success\"}]`), nil, nil","handlingStrategy":"validation","validationCode":"// sanity-check gh output before handing it to parsers\nout, err := exec.Command(\"gh\", \"run\", \"list\", \"--workflow=ci.yml\", \"-R\", repo, \"--json\", \"databaseId\").Output()\nif err == nil {\n    var probe []json.RawMessage\n    if json.Unmarshal(out, &probe) != nil || len(out) == 0 {\n        return errors.New(\"gh did not return a JSON array; check gh version and --json support\")\n    }\n}","typeGuard":null,"tryCatchPattern":"runs, err := queryGitHubRunsForWorkflow(\"ci.yml\", 5)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"parse gh output:\") {\n        log.Printf(\"gh returned unexpected output; upgrade gh or fix runner stdout: %v\", err)\n        return nil\n    }\n    return err\n}","preventionTips":["Pin/upgrade gh to a version supporting all --json fields your parser expects.","Never pipe gh output through text filters before parsing; disable pagers (GH_PAGER=).","Ensure custom runners return raw gh stdout only.","Unit-test the JSON contract with a golden fixture of gh run list output."],"tags":["json","github","cli","parse-error"],"backgroundTag":"unexpected-cli-output-format","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}