{"record":{"id":"191891f8831c3606","repo":"affaan-m/ECC","slug":"tool-fixture-corrupt","errorCode":"tool.fixture_corrupt","errorMessage":"fixture ${key.slice(0, 16)} is not valid JSON","messagePattern":"fixture (.+?) is not valid JSON","errorType":"error_code","errorClass":"ReplayError","httpStatus":null,"severity":"error","filePath":"scripts/lib/eval-harness/replay.js","lineNumber":74,"sourceCode":"      args_hash: hashValue(args),\n      response_hash: hashValue(response),\n      response,\n    };\n    fs.writeFileSync(this.pathFor(key), canonicalJson(record) + '\\n', 'utf8');\n    return record;\n  }\n\n  get(tool, args) {\n    const key = this.key(tool, args);\n    const filePath = this.pathFor(key);\n    if (!fs.existsSync(filePath)) {\n      throw new ReplayError('tool.fixture_missing', `no fixture for ${tool} (${key.slice(0, 16)})`, { tool, key });\n    }\n    let record;\n    try {\n      record = JSON.parse(fs.readFileSync(filePath, 'utf8'));\n    } catch (_error) {\n      throw new ReplayError('tool.fixture_corrupt', `fixture ${key.slice(0, 16)} is not valid JSON`, { tool, key });\n    }\n    if (record.tool !== tool || record.args_hash !== hashValue(args)) {\n      throw new ReplayError('tool.fixture_mismatch', `fixture ${key.slice(0, 16)} was recorded for different arguments`, { tool, key });\n    }\n    if (record.response_hash !== hashValue(record.response)) {\n      throw new ReplayError('tool.fixture_mismatch', `fixture ${key.slice(0, 16)} response hash does not match its content`, { tool, key });\n    }\n    return record;\n  }\n}\n\n/**\n * tools: { name: { effect_class, determinism: 'deterministic'|'nondeterministic', impl(args) } }\n * options: { mode: 'record'|'replay', store: FixtureStore, maxEffectClass: 'SE2', onCall(entry) }\n */\nfunction createReplayer(tools, options = {}) {\n  const mode = options.mode || 'replay';\n  const store = options.store;","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/eval-harness/replay.js#L56-L92","documentation":"FixtureStore.get throws ReplayError('tool.fixture_corrupt') when the fixture file exists but its contents cannot be parsed as JSON. This is a fail-closed integrity check: replay must refuse a fixture whose payload cannot be trusted instead of returning garbage. The short key prefix in the message identifies which fixture file to inspect.","triggerScenarios":"store.get(tool, args) reads `${key}.json` and JSON.parse throws — e.g. the file was truncated mid-write, hand-edited with a syntax error, saved with a BOM or invalid encoding, or overwritten by a non-JSON process.","commonSituations":"Manually editing fixture files to tweak recorded responses; a crash (Ctrl+C, OOM) during store.put's writeFileSync leaving a partial file; merge conflicts inside a fixture file resolved incorrectly; transferring fixtures between machines with encoding conversion.","solutions":["Delete the corrupt fixture file `${key}.json` from the store directory and re-run the eval in mode 'record' to regenerate it from the live implementation.","Inspect the file with a JSON validator (e.g. `node -e \"JSON.parse(require('fs').readFileSync('<file>','utf8'))\"`) to see the exact parse error before deleting, in case it is trivially fixable.","Check git status / merge conflict markers in the fixtures directory — a conflicted or partially staged fixture is a common cause.","Regenerate all fixtures if several are corrupt: wipe the store directory and run the full record pass once."],"exampleFix":"// before: hand-edited fixture with trailing comma\n{\"response\": {\"temp\": 21,}}\n\n// after: regenerate via record mode (or fix to valid JSON)\nconst r = createReplayer(tools, { mode: 'record', store });\nr.call('fetchWeather', recordedArgs);","handlingStrategy":"try-catch","validationCode":"const raw = fs.readFileSync(fixturePath, 'utf8');\ntry { JSON.parse(raw); } catch (e) { regenerateFixture(tool, args); }","typeGuard":"function isParsableJson(text) {\n  try { JSON.parse(text); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  return replayer.call(tool, args);\n} catch (e) {\n  if (e instanceof ReplayError && e.code === 'tool.fixture_corrupt') {\n    fs.unlinkSync(store.pathFor(e.key));\n    return recordAndReturn(tool, args);\n  }\n  throw e;\n}","preventionTips":["Never hand-edit fixture files; regenerate them via record mode","Avoid interrupting record runs mid-write; let record mode complete","Resolve git conflicts in fixtures by regenerating, not by manual merge","Add a lint/CI check that every fixture file parses as JSON"],"tags":["fixture","json","corruption","replay"],"backgroundTag":"json-parse-error","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}