{"record":{"id":"49cdc95d184d0c36","repo":"JuliusBrussee/caveman","slug":"journal-bytes-do-not-match-declared-transaction-st","errorCode":null,"errorMessage":"journal bytes do not match declared transaction state","messagePattern":"journal bytes do not match declared transaction state","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":12411,"sourceCode":"    || !validOptionalHash(value.config_after_sha256)\n    || !validOptionalHash(value.marker_before_sha256)\n    || !validOptionalHash(value.marker_after_sha256)) {\n    throw new Error(`pending ${label} transaction is malformed; refusing recovery`);\n  }\n  try {\n    const configBefore = decodePendingBytes(value.config_before_base64, \"config_before_base64\");\n    const markerBefore = decodePendingBytes(value.marker_before_base64, \"marker_before_base64\");\n    const markerAfter = decodePendingBytes(value.marker_after_base64, \"marker_after_base64\");\n    if (optionalBytesHash(configBefore) !== value.config_before_sha256\n      || optionalBytesHash(markerBefore) !== value.marker_before_sha256\n      || optionalBytesHash(markerAfter) !== value.marker_after_sha256\n      || (markerBefore !== null && !validMcpMarkerBytes(markerBefore, journalAgent, journalServer))\n      || (markerAfter !== null && !validMcpMarkerBytes(markerAfter, journalAgent, journalServer))\n      || (markerBefore !== null && parseMcpServerMarkerBytes(journalAgent, journalServer, markerBefore)?.config_path !== undefined\n        && parseMcpServerMarkerBytes(journalAgent, journalServer, markerBefore)?.config_path !== value.config_path)\n      || (markerAfter !== null && parseMcpServerMarkerBytes(journalAgent, journalServer, markerAfter)?.config_path !== value.config_path)\n      || (value.action === \"install\") !== (markerAfter !== null)) {\n      throw new Error(\"journal bytes do not match declared transaction state\");\n    }\n    return {\n      journal: value as OwnedMcpPendingJournal,\n      configBefore,\n      markerBefore,\n      markerAfter,\n      path,\n      bytes,\n    };\n  } catch (error) {\n    throw new Error(`pending ${label} transaction is malformed: ${(error as Error).message}`);\n  }\n}\n\nfunction readOwnedMcpPendingLocator(agent: \"kilo\" | \"qwen\", serverName: string): ReadOwnedMcpPendingJournal | null {\n  const path = canonicalMcpConfigPath(mcpPendingJournalPath(agent, serverName));\n  return readOwnedMcpPendingJournalAt(path, { agent, serverName, locatorPath: path });\n}","sourceCodeStart":12393,"sourceCodeEnd":12429,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L12393-L12429","documentation":"Thrown after field-level validation when the decoded journal bytes are internally inconsistent with the declared transaction: marker bytes don't parse as valid MCP server markers for the agent/server, a marker's embedded config_path disagrees with journal config_path, config/marker hashes don't match the decoded bytes, or the action ('install') doesn't agree with markerAfter being present/absent. It is a final integrity check that prevents applying a self-contradictory journal.","triggerScenarios":"A journal whose config_before_base64 bytes hash to something other than config_before_sha256; marker files saved under the wrong agent/serverName; action=install but marker_after_base64 is null; a marker whose internal config_path differs from journal config_path.","commonSituations":"Partially edited journals; journals copied between different MCP server configurations; a writer bug mixing marker bytes from another server; corruption that passes JSON validation but breaks cross-field consistency.","solutions":["Verify hashes: recompute sha256 of the decoded base64 fields and confirm they equal the *_sha256 fields.","Confirm the journal belongs to this agent/serverName and config_path; discard journals from other servers.","Ensure action and marker_after are consistent: install ⇒ marker_after present; uninstall ⇒ null.","Delete the inconsistent .pending journals and redo the transaction cleanly."],"exampleFix":"// before\n{ \"action\": \"install\", \"marker_after_base64\": null, ... }\n// after\n{ \"action\": \"install\", \"marker_after_base64\": \"<valid marker bytes>\", ... }","handlingStrategy":"validation","validationCode":"// verify cross-field consistency before recovery\nconst h = b => 'sha256:' + require('crypto').createHash('sha256').update(b).digest('hex');\nif (configBefore && h(configBefore) !== j.config_before_sha256) throw new Error('hash mismatch');\nif ((j.action === 'install') !== (j.marker_after_base64 !== null)) throw new Error('action/marker mismatch');","typeGuard":null,"tryCatchPattern":"try { recoverPending(); } catch (e) {\n  if (e.message === 'journal bytes do not match declared transaction state') { /* discard journal; redo transaction */ }\n}","preventionTips":["Recompute and compare hashes of decoded bytes whenever you touch a journal.","Keep marker bytes, agent/serverName, and config_path mutually consistent at write time.","Never partially update one field of a journal; write it atomically."],"tags":["journal-integrity","checksum-mismatch","state-consistency"],"backgroundTag":"checksum-mismatch","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-09-06T12:00:26.372Z","contentChangedAt":"2026-09-06T12:00:26.372Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}