{"record":{"id":"dc3471466a9ca00e","repo":"JuliusBrussee/caveman","slug":"empty-version-output","errorCode":null,"errorMessage":"empty version output","messagePattern":"empty version output","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":431,"sourceCode":"function compareNodeVersion(current: string, minimum: string): number {\n  const parse = (value: string) => value.split(\".\").slice(0, 3).map((part) => Number(part));\n  const left = parse(current);\n  const right = parse(minimum);\n  for (let index = 0; index < 3; index++) {\n    const difference = (left[index] ?? 0) - (right[index] ?? 0);\n    if (difference !== 0) return difference;\n  }\n  return 0;\n}\n\nfunction safeDiagnostic(error: unknown): string {\n  const value = error instanceof Error ? error.message : String(error);\n  return value.replace(/[\\r\\n]+/g, \" \").slice(0, 512);\n}\n\nfunction runtimeVersionDiagnostic(stdout: string): string {\n  const value = stdout.trim();\n  if (value === \"\") throw new Error(\"empty version output\");\n  try {\n    const parsed = JSON.parse(value) as { version?: unknown; binary_release?: unknown };\n    if (typeof parsed.version === \"string\" && parsed.version.trim() !== \"\") {\n      const release = typeof parsed.binary_release === \"string\" && parsed.binary_release.trim() !== \"\"\n        ? ` (${parsed.binary_release.trim()})`\n        : \"\";\n      return `caveman ${parsed.version.trim()}${release}`;\n    }\n  } catch {\n    // Older CLIs may return one plain version line.\n  }\n  return value.replace(/[\\r\\n]+/g, \" \").slice(0, 256);\n}\n\nfunction credentialForModel(model: string): { name: string; available: boolean } {\n  const provider = model.split(\"/\", 1)[0];\n  if (provider === \"anthropic\") {\n    return { name: \"ANTHROPIC_API_KEY\", available: Boolean(process.env.ANTHROPIC_API_KEY) };","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/cli.ts#L413-L449","documentation":"runtimeVersionDiagnostic() parses the stdout of an external `caveman` runtime CLI to build a human-readable version string. Trimmed stdout was empty — the process produced no output — so there is nothing to report and it throws instead of fabricating a version. Any non-empty output is handled (JSON with version/binary_release, or a legacy plain line).","triggerScenarios":"The version-probe subprocess (caveman runtime CLI) exits producing zero bytes on stdout: binary found but broken (crashes before printing), wrong executable shadowing the real one (an empty stub script earlier in PATH), or output redirected/swallowed by a wrapper.","commonSituations":"PATH pointing at a shim/wrapper script that swallows stdout; a half-installed or architecture-mismatched binary that dies silently; CI layer caching a truncated binary; Windows batch shim quirks.","solutions":["Run the runtime binary directly (`caveman --version` or equivalent) and confirm it prints a version; if empty, reinstall it.","Check PATH ordering for stub scripts shadowing the real caveman binary (which -a caveman).","If a wrapper script is involved, make sure it forwards stdout instead of consuming it."],"exampleFix":"# before: shim swallows output\n#!/bin/sh\nexec /opt/caveman/bin/caveman \"$@\" >/dev/null  # stdout discarded\n\n# after\n#!/bin/sh\nexec /opt/caveman/bin/caveman \"$@\"","handlingStrategy":"validation","validationCode":"import { execFileSync } from \"node:child_process\";\nfunction assertRuntimeReportsVersion(bin = \"caveman\"): string {\n  const out = execFileSync(bin, [\"--version\"], { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] }).trim();\n  if (out === \"\") throw new Error(`${bin} produced no version output; check PATH shim`);\n  return out;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Smoke-test `caveman --version` in CI before jobs that probe the runtime version.","Audit PATH for wrapper scripts that discard stdout (which -a caveman).","Reinstall the runtime binary if it crashes before printing — empty output means a broken install, not a parse quirk."],"tags":["cli","environment","subprocess","diagnostics"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}