{"record":{"id":"10910b95a8faaa5d","repo":"JuliusBrussee/caveman","slug":"aider-caveman-config-block-changed-after-enable-r","errorCode":null,"errorMessage":"Aider Caveman config block changed after enable; refusing destructive disable","messagePattern":"Aider Caveman config block changed after enable; refusing destructive disable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":8391,"sourceCode":"    }\n    if (mcp.caveman !== undefined) {\n      if (operation.owned?.previous_mcp === null || operation.owned?.previous_mcp === undefined) delete mcp.caveman;\n      else mcp.caveman = operation.owned.previous_mcp;\n    }\n    if (Object.keys(mcp).length > 0) root.mcp = mcp;\n    else delete root.mcp;\n    return jsonBytes(root);\n  }\n  if (operation.kind === \"aider-config\") {\n    let text = current.toString(\"utf8\");\n    const routeBlock = operation.owned?.route_block;\n    const readBlock = operation.owned?.read_block;\n    const previousRouteLine = operation.owned?.previous_route_line;\n    if (typeof routeBlock !== \"string\" || typeof readBlock !== \"string\") {\n      throw new Error(\"Aider integration journal lacks owned blocks\");\n    }\n    if (!text.includes(routeBlock) || !text.includes(readBlock)) {\n      throw new Error(\"Aider Caveman config block changed after enable; refusing destructive disable\");\n    }\n    text = text.replace(routeBlock, typeof previousRouteLine === \"string\" ? previousRouteLine : \"\");\n    text = text.replace(readBlock, \"\");\n    return Buffer.from(text.replace(/\\n{3,}/g, \"\\n\\n\"));\n  }\n  if (operation.kind === \"aider-core\") {\n    throw new Error(`${operation.file} changed after enable; refusing destructive disable`);\n  }\n  if (operation.kind === \"hermes-plugin-manifest\" || operation.kind === \"hermes-plugin-init\") {\n    throw new Error(`${operation.file} changed after enable; refusing destructive disable`);\n  }\n  if (operation.kind === \"hermes-config\") {\n    let text = current.toString(\"utf8\");\n    const routeBlock = operation.owned?.route_block;\n    const previousRouteLines = operation.owned?.previous_route_lines;\n    if (typeof routeBlock !== \"string\" || !Array.isArray(previousRouteLines)) {\n      throw new Error(\"Hermes integration journal lacks owned routing block\");\n    }","sourceCodeStart":8373,"sourceCodeEnd":8409,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L8373-L8409","documentation":"When rolling back the Aider config, the tool verifies both journaled blocks are still present verbatim in the file. If route_block or read_block is no longer found in the text, the file was modified after enable and the tool refuses to disable destructively rather than producing a broken config.","triggerScenarios":"Running disable with kind === \"aider-config\" when text.includes(routeBlock) or text.includes(readBlock) is false — the user (or a formatter/another tool) edited, reformatted, or partially removed the Caveman blocks in the Aider config after enable.","commonSituations":"Manual cleanup of .aider.conf.yml that changed whitespace/comments inside the block; reformatting tool collapsed lines; user commented the block out.","solutions":["Restore the Caveman blocks to their exact journaled content (or restore the file from backup/git), then re-run disable.","Manually delete the Caveman blocks from the Aider config instead of using disable.","Re-run enable to overwrite the blocks and refresh the journal, then disable."],"exampleFix":"// before: block edited after enable\n# caveman-start\nmodel: openrouter/x  # changed line\n# caveman-end\n// after: exact original block restored\n# caveman-start\nmodel: openrouter/caveman\n# caveman-end","handlingStrategy":"validation","validationCode":"const text = fs.readFileSync(aiderConfig, 'utf8');\nconst { route_block: rb, read_block: db } = journal.owned ?? {};\nif (typeof rb !== 'string' || typeof db !== 'string' || !text.includes(rb) || !text.includes(db)) {\n  throw new Error('Aider config drift detected; restore blocks before disable');\n}","typeGuard":"const blocksIntact = (text, owned) =>\n  typeof owned?.route_block === 'string' && text.includes(owned.route_block) &&\n  typeof owned?.read_block === 'string' && text.includes(owned.read_block);","tryCatchPattern":"try {\n  await caveman.disable(['aider']);\n} catch (err) {\n  if (err.message.includes('Aider Caveman config block changed')) {\n    console.error('Restore .aider.conf.yml blocks (git checkout) or remove them manually.');\n  } else throw err;\n}","preventionTips":["Commit or back up .aider.conf.yml before enabling.","Don't edit lines inside the marked Caveman blocks.","Run formatters that preserve block contents, or exclude the config from reformatting.","If a manual edit happened, re-run enable to refresh the journal before disable."],"tags":["config","aider","disable-safety"],"backgroundTag":"conflicting-config-options","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}