{"record":{"id":"92b006e73c618e49","repo":"can1357/oh-my-pi","slug":"invalid-json-error-instanceof-error-error-mes","errorCode":null,"errorMessage":"invalid JSON: ${error instanceof Error ? error.message : String(error)}","messagePattern":"invalid JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cleanse/checkers.ts","lineNumber":500,"sourceCode":"\t\t[cargo, \"metadata\", \"--no-deps\", \"--format-version=1\", \"--manifest-path\", manifest],\n\t\t{\n\t\t\tcwd: path.resolve(state.projectCwd, root),\n\t\t\tstderr: \"full\",\n\t\t\tallowNonZero: true,\n\t\t},\n\t);\n\tif (!result.ok) {\n\t\tthrow new Error(\n\t\t\tsanitizeText(result.stderr || result.stdout)\n\t\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t\t.trim(),\n\t\t);\n\t}\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(result.stdout);\n\t} catch (error) {\n\t\tthrow new Error(`invalid JSON: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n\tif (!isRecord(parsed)) throw new Error(\"metadata root is not an object\");\n\tconst workspaceMembers = new Set<string>();\n\tif (Array.isArray(parsed.workspace_members)) {\n\t\tfor (const member of parsed.workspace_members) {\n\t\t\tif (typeof member === \"string\") workspaceMembers.add(member);\n\t\t}\n\t}\n\tconst allowedFiles = new Set(state.files);\n\tconst packages: string[] = [];\n\tif (!Array.isArray(parsed.packages)) return packages;\n\tfor (const value of parsed.packages) {\n\t\tif (!isRecord(value) || typeof value.id !== \"string\" || !workspaceMembers.has(value.id)) continue;\n\t\tif (typeof value.name !== \"string\" || typeof value.manifest_path !== \"string\") continue;\n\t\tconst relativeManifest = path.relative(state.projectCwd, value.manifest_path).split(path.sep).join(\"/\");\n\t\tif (allowedFiles.has(relativeManifest)) packages.push(value.name);\n\t}\n\treturn [...new Set(packages)].sort();","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cleanse/checkers.ts#L482-L518","documentation":"After a successful cargo metadata run, cargoWorkspacePackages() JSON.parses the captured stdout. If parsing fails it rethrows 'invalid JSON: <parse error>'. Since cargo was invoked with --format-version 1, this usually means the stdout was polluted by non-JSON output (warnings, progress lines) or a different cargo wrote human-readable text.","triggerScenarios":"JSON.parse(result.stdout) throws because cargo printed extra non-JSON text to stdout (build scripts/progress), an old cargo ignores --format-version, or the captured stream mixed stderr into stdout.","commonSituations":"Custom cargo wrappers or .cargo/config printing banners; very old cargo versions; environment wrappers (e.g. cargo wrapped by sccache/Nix shims) emitting output before the JSON.","solutions":["Run `cargo metadata --format-version 1` manually and confirm stdout is pure JSON","Remove or bypass wrappers/shims that print to stdout before cargo's JSON","Update cargo/rustup to a current version that honors --format-version","If you own the code, parse only the first line that starts with '{' or capture with stderr fully separated"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isCargoMetadataJson(stdout: string): boolean {\n  try {\n    const v: unknown = JSON.parse(stdout);\n    return typeof v === \"object\" && v !== null && !Array.isArray(v);\n  } catch { return false; }\n}","typeGuard":"function isRecord(v: unknown): v is Record<string, unknown> {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  return await cargoWorkspacePackages(state);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('invalid JSON')) {\n    logger.warn(\"cargo metadata produced non-JSON stdout; check cargo wrappers\", {});\n    return [];\n  }\n  throw err;\n}","preventionTips":["Keep stdout clean: no wrappers/shims that echo banners around cargo","Use a current cargo that honors --format-version 1","Capture stderr separately from stdout when shelling cargo yourself","Pin/verify the toolchain (rust-toolchain.toml) so environments are consistent"],"tags":["rust","cargo","json-parsing"],"backgroundTag":"invalid-json-output","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}