affaan-m/ECC · error · CapsuleError

state.reason

Error message

state.reason

What it means

Capsule.open reads the capsule via readCapsule(dir); if the read fails (corrupt journal, missing/bad meta file, checksum mismatch, etc.) it returns { ok: false, code, reason, failed_at }, and open rethrows it as a CapsuleError with the failure's code and reason (message 'state.reason' — real text comes from readCapsule) plus failed_at as context. The message 'state.reason' means the on-disk capsule state could not be validated as openable.

Solutions

  1. Inspect state.code / the error message to identify the exact failure (missing meta, bad schema version, corrupt entry, checksum mismatch)
  2. If the journal is corrupt, restore the capsule from backup or truncate to the last verified entry after backing up the raw files
  3. Re-run the eval to regenerate the capsule if its contents are reproducible and the data is disposable
  4. Do not hand-edit meta or journal files; regenerate or restore them with tooling that preserves the hash chain

Example fix

// before
const capsule = Capsule.open('./out'); // throws on any bad state
// after
let capsule;
try {
  capsule = Capsule.open('./out');
} catch (e) {
  console.error('cannot open capsule:', e.code, e.message, e.failed_at);
  fs.renameSync('./out', `./out.corrupt-${Date.now()}`);
  capsule = Capsule.create('./out');
}
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs');
const path = require('path');
function capsuleDirLooksIntact(dir) {
  const resolved = path.resolve(dir);
  if (!fs.existsSync(resolved)) return false;
  return fs.existsSync(path.join(resolved, 'meta.json'));
}

Try / catch

let capsule;
try {
  capsule = Capsule.open(dir);
} catch (e) {
  console.error('open failed:', e.code, e.message, 'failed_at:', e.failed_at);
  // restore from backup or regenerate before retrying
  throw e;
}

Prevention

When it happens

Trigger: Opening a directory that is not a valid capsule (missing meta file, wrong schema version); opening a capsule whose journal contains a corrupted entry or a hash that fails verification; reading a capsule from a partially-written or truncated state (crash mid-write); opening a directory with wrong permissions so reads fail.

Common situations: A crash or SIGKILL during append leaving a partial journal line; hand-editing the journal or meta JSON; copying a capsule without all files; restoring from a partial backup; schema version drift after upgrading the harness.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/ebd4a76e4da6f1f9. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/eval-harness/capsule.js:163

      run_id: options.run_id === undefined ? newId('run') : options.run_id,
      capsule_id: options.capsule_id === undefined ? newId('capsule') : options.capsule_id,
      harness_version: options.harness_version === undefined ? 'unknown' : options.harness_version,
      task_family: options.task_family === undefined ? 'unspecified' : options.task_family,
      created_at: nowIso(options.clock),
    };
    const failure = metadataFailure(meta);
    if (failure) throw new CapsuleError(failure.code, failure.reason);
    fs.mkdirSync(resolved, { recursive: true });
    fs.writeFileSync(path.join(resolved, META_FILE), canonicalJson(meta) + '\n', 'utf8');
    fs.writeFileSync(path.join(resolved, JOURNAL_FILE), '', 'utf8');
    return new Capsule(resolved, meta, options);
  }

  static open(dir, options = {}) {
    const resolved = path.resolve(dir);
    const state = readCapsule(resolved);
    if (!state.ok) {
      throw new CapsuleError(state.code, state.reason, { failed_at: state.failed_at });
    }
    const capsule = new Capsule(resolved, state.meta, options);
    if (state.entries.length > 0) {
      const last = state.entries[state.entries.length - 1];
      capsule.lastHash = last.entry_hash;
      capsule.nextSeq = last.seq + 1;
    }
    return capsule;
  }

  /**
   * Serialize cooperating appenders and validate current disk state under lock.
   * A partial I/O failure is preserved for diagnosis, never silently rolled back.
   */
  append(lineage, kind, payload = {}, options = {}) {
    return withAppendLock(this.dir, () => {
      const state = readCapsule(this.dir);
      if (!state.ok) throw new CapsuleError(state.code, state.reason, { failed_at: state.failed_at });

View on GitHub (pinned to 8321021c54)