{"record":{"id":"4ba193ca3c54f70d","repo":"JuliusBrussee/caveman","slug":"existing-hermes-caveman-native-block-is-unjournale","errorCode":null,"errorMessage":"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`","messagePattern":"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":6692,"sourceCode":"  end: string,\n  blockLines: string[],\n): string | null {\n  const section = topLevelSection(lines, sectionName);\n  if (section) {\n    if (sectionHasChildKey(lines, section, childName)) return null;\n    lines.splice(section.start + 1, 0, ...blockLines);\n    return blockLines.join(\"\\n\");\n  }\n  if (lines.length > 0 && lines[lines.length - 1]!.trim()) lines.push(\"\");\n  const body = blockLines.filter((line) => !line.includes(begin) && !line.includes(end));\n  const whole = [begin, `${sectionName}:`, ...body, end];\n  lines.push(...whole);\n  return whole.join(\"\\n\");\n}\n\nfunction hermesNativeConfig(source: string, gw: string, mcpBinary: string): { text: string; owned: Record<string, unknown> } {\n  for (const marker of [HERMES_NATIVE_ROUTE_BEGIN, HERMES_NATIVE_ROUTE_END, HERMES_NATIVE_PLUGIN_BEGIN, HERMES_NATIVE_PLUGIN_END, HERMES_NATIVE_MCP_BEGIN, HERMES_NATIVE_MCP_END]) {\n    if (source.includes(marker)) throw new Error(\"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`\");\n  }\n  const lines = yamlLines(source);\n  let model = topLevelSection(lines, \"model\");\n  if (!model) {\n    lines.unshift(\"model:\");\n    model = topLevelSection(lines, \"model\")!;\n  }\n  const routeIndexes: number[] = [];\n  const previousRouteLines: string[] = [];\n  for (let i = model.start + 1; i < model.end; i++) {\n    if (/^  (provider|base_url):/.test(lines[i]!)) {\n      routeIndexes.push(i);\n      previousRouteLines.push(lines[i]!);\n    }\n  }\n  if (new Set(routeIndexes.map((index) => lines[index]!.match(/^  ([^:]+):/)?.[1])).size !== routeIndexes.length) {\n    throw new Error(\"Hermes model provider/base_url keys are duplicated; refusing ambiguous install\");\n  }","sourceCodeStart":6674,"sourceCodeEnd":6710,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/index.ts#L6674-L6710","documentation":"hermesNativeConfig() stamps managed blocks into the Hermes YAML config delimited by HERMES_NATIVE_ROUTE/PLUGIN/MCP BEGIN/END markers. If any of these markers is already present in the source while no journal covers it (fresh install path), the file contains a Caveman block Caveman cannot account for, so it refuses to merge.","triggerScenarios":"Native Hermes install when the Hermes config file already contains any HERMES_NATIVE_* BEGIN/END marker string (e.g. restored from backup, or journal under ~/.caveman was wiped).","commonSituations":"Restoring the Hermes config from backups or dotfiles after resetting ~/.caveman; reusing a config from another machine; remnants of a previous install.","solutions":["Run `caveman doctor hermes` to reconcile the unjournaled block","Or delete every HERMES_NATIVE marker-delimited block (BEGIN through END inclusive) from the Hermes config, then retry","Keep ~/.caveman state and agent configs in sync when restoring from backups"],"exampleFix":"# before — hermes config carries orphan markers\n# <<< CAVEMAN NATIVE ROUTE BEGIN <<<\n  provider: \"custom\"\n  base_url: \"http://127.0.0.1:8080/w/hermes\"\n# <<< CAVEMAN NATIVE ROUTE END <<<\n\n# after — block removed (or `caveman doctor hermes`), then install re-stamps journaled blocks","handlingStrategy":"validation","validationCode":"import { readFileSync } from \"node:fs\";\nconst HERMES_MARKERS = [HERMES_NATIVE_ROUTE_BEGIN, HERMES_NATIVE_ROUTE_END, HERMES_NATIVE_PLUGIN_BEGIN, HERMES_NATIVE_PLUGIN_END, HERMES_NATIVE_MCP_BEGIN, HERMES_NATIVE_MCP_END];\nfunction hermesConfigClean(path: string): boolean {\n  try { const src = readFileSync(path, \"utf8\"); return !HERMES_MARKERS.some((m) => src.includes(m)); }\n  catch { return true; }\n}","typeGuard":null,"tryCatchPattern":"try { nativeInstallHermes(); } catch (e) {\n  if (e instanceof Error && /unjournaled/.test(e.message)) {\n    spawnSync(\"caveman\", [\"doctor\", \"hermes\"], { stdio: \"inherit\" });\n    nativeInstallHermes();\n  } else throw e;\n}","preventionTips":["Sync ~/.caveman state and Hermes config when restoring from backup/dotfiles","Don't hand-copy Caveman-marked blocks between environments","Use caveman doctor hermes after manual config surgery"],"tags":["hermes","yaml","markers","journal","corruption"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}