JuliusBrussee/caveman · error · Error

${target} integration journal disappeared during repair

Error message

${target} integration journal disappeared during repair

What it means

repairNativeAgent first checks that either the committed journal or a pending journal exists, then inside the integration lock runs crash recovery (recoverPendingNativeInstallUnlocked) and re-reads the committed journal; this error means the re-read found nothing. The usual cause is that a pending (crashed) transaction was rolled back by recovery — leaving no committed journal — or a concurrent `caveman disable <agent>` deleted the journal between the two reads.

Source

Thrown at packages/cli/src/index.ts:8294

    return false;
  }
  cleanupNativeAgentFiles(target, disabled);
  const name = findAgent(target)?.display_name ?? target;
  process.stderr.write(`${mark("ok")} ${name}: ${target === "aider" ? "shallow" : "native"} Caveman disabled; unrelated host edits preserved\n`);
  return true;
}

function repairNativeAgent(target: NativeAgent): void {
  if (!readNativeJournal(target) && !readPendingNativeJournal(target)) {
    enableNative([target]);
    return;
  }
  const profile = findAgent(target)!;
  const gw = gatewayURL();
  withIntegrationLock(target, () => {
    recoverPendingNativeInstallUnlocked(target);
    const journal = readNativeJournal(target);
    if (!journal) throw new Error(`${target} integration journal disappeared during repair`);
    if (!which(binOf(profile))) throw new Error(`${profile.display_name} not found on PATH`);
    const mcpBinary = target === "aider" ? undefined : nativeMcpBinaryRequired();
    nativeProxyBinaryRequired(gw);
    const journalBytes = readFileSync(nativeJournalPath(target));
    const current = restoreNativeJournalFiles(journal);
    try {
      const mutations = nativeMutationsFor(target, gw, mcpBinary);
      applyNativeMutations(target, profile, mutations);
    } catch (error) {
      for (const item of current) {
        try { writeNativeRestoration(item.file, item.bytes); } catch { /* original error remains authority */ }
      }
      atomicWriteFile(nativeJournalPath(target), journalBytes);
      throw error;
    }
  });
  process.stderr.write(`${mark("ok")} ${profile.display_name}: native Caveman repaired; unrelated host edits preserved\n`);
}

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Simply rerun `caveman doctor <agent> --fix` — with both journals now absent, it takes the enableNative path and rebuilds the integration cleanly
  2. Make sure no other caveman disable/enable/doctor command for the same agent is running concurrently; run integration commands serially
  3. If it recurs without concurrency, check for external deletion of ~/.caveman/integrations/<agent>.json (cron, dotfile cleaners)

Example fix

# before: recovery rolled back a pending enable, journal gone
caveman doctor claude --fix
# >> claude integration journal disappeared during repair

# after: state is now consistent; rerun rebuilds the integration
caveman doctor claude --fix
Defensive patterns

Strategy: retry

Validate before calling

// Ensure no concurrent integration command and journals are stable before repair
import { existsSync } from 'node:fs';
const home = process.env.CAVEMAN_HOME ?? `${process.env.HOME}/.caveman`;
const committed = `${home}/integrations/codex.json`;
const pending = `${home}/integrations/.pending-codex.json`;
// snapshot twice with a beat between; require stability if you plan to repair
const snap = () => [committed, pending].map((p) => existsSync(p)).join(',');
const a = snap(); await new Promise((r) => setTimeout(r, 250));
if (snap() !== a) console.error('journal state changing — another caveman process is active');

Try / catch

catch (err) {
  if (err.message.includes('journal disappeared during repair')) {
    // state resolved (pending rolled back or concurrent disable finished):
    // re-check and run the command again from scratch — it now takes the enable path
    return execSync('caveman doctor codex --fix');
  }
  throw err;
}

Prevention

When it happens

Trigger: `caveman doctor <agent> --fix` when a crashed `caveman enable <agent>` left a .pending-<agent>.json that recovery rolls back (enable never committed), or when another terminal runs `caveman disable <agent>` at the same moment. A journal file deleted by hand mid-command also triggers it.

Common situations: Interrupting an enable (Ctrl-C, machine sleep, crash) and then immediately running doctor --fix; running disable and doctor concurrently from two shells; scripts invoking multiple caveman integration commands in parallel.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-18). Data as JSON: /api/errors/d6050e5ddd7260fa. Report an issue: GitHub.