{"record":{"id":"c54aae4c93c65197","repo":"affaan-m/ECC","slug":"command-args-join-failed-result-std","errorCode":null,"errorMessage":"${command} ${args.join(' ')} failed: ${(result.stderr || result.stdout || '').trim()}","messagePattern":"(.+?) (.+?) failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/gh-api.js","lineNumber":49,"sourceCode":"\nfunction normalizeLabels(labels) {\n  return Array.from(new Set((Array.isArray(labels) ? labels : []).map(normalizeLabelValue).filter(Boolean))).sort();\n}\n\nfunction runCommand(command, args, options = {}) {\n  const result = spawnSync(command, args, {\n    cwd: options.cwd,\n    env: options.env || process.env,\n    encoding: 'utf8',\n    maxBuffer: 10 * 1024 * 1024,\n  });\n\n  if (result.error) {\n    throw new Error(`${command} ${args.join(' ')} failed: ${result.error.message}`);\n  }\n\n  if (result.status !== 0) {\n    throw new Error(`${command} ${args.join(' ')} failed: ${(result.stderr || result.stdout || '').trim()}`);\n  }\n\n  return result.stdout || '';\n}\n\n// ECC_GH_SHIM creates a trust boundary: when set, shimPath replaces the real\n// `gh` binary and command/commandArgs execute an arbitrary script via\n// process.execPath. This variable MUST only be set in trusted, isolated test\n// environments (e.g., a test's own temp directory). Never set ECC_GH_SHIM in\n// production — doing so allows arbitrary script execution under the caller's\n// privileges.\nfunction runGh(args, options = {}) {\n  const shimPath = process.env.ECC_GH_SHIM;\n  const command = shimPath ? process.execPath : 'gh';\n  const commandArgs = shimPath ? [shimPath, ...args] : args;\n  const env = { ...process.env };\n\n  if (options.stripGithubToken) {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/github-coordination/gh-api.js#L31-L67","documentation":"Thrown by runCommand when the child process spawned successfully but exited with a non-zero status. The message includes the trimmed stderr (falling back to stdout) so the caller sees gh's own error output. Common causes are auth failures, rate limits, missing resources, or invalid gh arguments.","triggerScenarios":"gh is not authenticated (gh auth status fails); the issue/repo does not exist; rate limited by the API; invalid gh flags; network failure mid-call; permissions/forbidden.","commonSituations":"CI without GH_TOKEN set; token expired or lacks scope; referencing a private repo the token can't read; gh version mismatch changing flag semantics; transient API errors.","solutions":["Read the embedded stderr to find the exact gh error (auth, not-found, rate-limit, forbidden).","Authenticate gh: run `gh auth login` or export GH_TOKEN with adequate scopes (repo, read:org).","For transient errors (rate limit, 5xx), retry with backoff.","Verify the repo/issue exists and the token can access it; fix any invalid gh flags."],"exampleFix":"// before\nrunGh(['issue', 'view', String(n), '--repo', repo]);\n\n// after — capture and rethrow with actionable context\ntry {\n  runGh(['issue', 'view', String(n), '--repo', repo]);\n} catch (e) {\n  if (/auth/i.test(e.message)) throw new Error('gh auth failed: run `gh auth login` or set GH_TOKEN');\n  if (/rate limit/i.test(e.message)) { await sleep(60000); throw e; }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"const { spawnSync } = require('child_process');\nconst auth = spawnSync('gh', ['auth', 'status'], { encoding: 'utf8' });\nif (auth.status !== 0) {\n  throw new Error('gh not authenticated: run `gh auth login` or set GH_TOKEN');\n}","typeGuard":"function ghAuthenticated() {\n  return spawnSync('gh', ['auth', 'status'], { encoding: 'utf8' }).status === 0;\n}","tryCatchPattern":"async function ghWithRetry(fn, retries = 3) {\n  for (let i = 0; i < retries; i++) {\n    try { return fn(); }\n    catch (e) {\n      if (/rate limit/i.test(e.message) && i < retries - 1) { await new Promise(r => setTimeout(r, 60000 * (i + 1))); continue; }\n      throw e;\n    }\n  }\n}","preventionTips":["Authenticate gh and set GH_TOKEN with adequate scopes in CI.","Retry with backoff on transient (rate-limit/5xx) stderr messages.","Parse the embedded stderr to map auth/not-found/forbidden to fixes."],"tags":["github-coordination","gh-api","spawn","auth","network"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}