{"record":{"id":"ae0652db945ffa0f","repo":"ruvnet/ruflo","slug":"rvfeventlog-invalid-file-header-in-filepath","errorCode":null,"errorMessage":"[RvfEventLog] Invalid file header in ${filePath}","messagePattern":"\\[RvfEventLog\\] Invalid file header in (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"v3/@claude-flow/shared/src/events/rvf-event-log.ts","lineNumber":341,"sourceCode":"    if (this.config.verbose) {\n      console.log('[RvfEventLog] persist() called — all data already on disk');\n    }\n  }\n\n  // ===========================================================================\n  // Private Helpers\n  // ===========================================================================\n\n  /**\n   * Replay an RVF file and invoke `handler` for every decoded record.\n   * Used both for events and snapshots.\n   */\n  private replayFile(filePath: string, handler: (record: any) => void): void {\n    const buf = readFileSync(filePath);\n\n    // Validate magic\n    if (buf.length < MAGIC_LENGTH || buf.subarray(0, MAGIC_LENGTH).compare(MAGIC) !== 0) {\n      throw new Error(`[RvfEventLog] Invalid file header in ${filePath}`);\n    }\n\n    let offset = MAGIC_LENGTH;\n\n    const MAX_PAYLOAD_SIZE = 100 * 1024 * 1024; // 100MB safety limit\n    while (offset + LENGTH_PREFIX_BYTES <= buf.length) {\n      const payloadLength = buf.readUInt32BE(offset);\n      offset += LENGTH_PREFIX_BYTES;\n\n      if (payloadLength > MAX_PAYLOAD_SIZE) {\n        if (this.config.verbose) {\n          console.warn(`[RvfEventLog] Payload size ${payloadLength} exceeds safety limit`);\n        }\n        break;\n      }\n\n      if (offset + payloadLength > buf.length) {\n        // Truncated record — stop reading (crash recovery).","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/events/rvf-event-log.ts#L323-L359","documentation":"When replaying a log file (for events or snapshots), RvfEventLog verifies the MAGIC byte prefix at offset 0 and throws if the file is shorter than the magic or the bytes differ. This fires when logPath points at a file that is not an RVF log, an empty or truncated file, or a log corrupted by a crash mid-write. The check is deliberately early so corrupt bytes never enter the in-memory index.","triggerScenarios":"Configuring logPath to a JSON-lines event log or other non-RVF file; replaying a zero-byte file left by a failed first write; a log truncated by a process crash or disk-full during appendRecord; a backup copied while the writer was active.","commonSituations":"Migrating from another event-store format and pointing at old logs; restoring partial backups; two event-log versions or apps sharing one path; interrupted copies via rsync/scp of a live log.","solutions":["Verify logPath targets a file this RvfEventLog version wrote (hex-dump the first bytes and compare against a known-good log)","If corrupted, restore the log from a intact backup, or rebuild from snapshots when they exist","Copy/backup log files only while the writer is stopped, and write via the append+rename path so torn files cannot be replayed"],"exampleFix":"// before\nnew RvfEventLog({ logPath: './data/events.jsonl' }); // wrong format -> throws on replay\n\n// after\nnew RvfEventLog({ logPath: './data/events.rvf' }); // file written by RvfEventLog itself","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs';\nfunction looksLikeRvfFile(path: string): boolean {\n  const head = readFileSync(path).subarray(0, 4); // MAGIC_LENGTH bytes\n  return head.length === 4 && head.equals(KNOWN_MAGIC_BYTES);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await log.initialize(); // replays the log\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Invalid file header')) {\n    // log is wrong-format or corrupt: restore from backup or rebuild from snapshots\n  } else throw e;\n}","preventionTips":["Verify the magic bytes of the target file before pointing logPath at it","Back up logs only while the writer is stopped","Keep event formats versioned; never point a new RvfEventLog at a foreign event file"],"tags":["event-sourcing","file-corruption","replay","event-log"],"backgroundTag":"file-corruption","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}