ruvnet/ruflo · error
RVFP header magic mismatch
Error message
RVFP header magic mismatch
What it means
After the outer binary preamble passes, the JSON header embedded at offset 12 must itself carry magic === 'RVFP'. This second check catches files whose envelope is genuine but whose header JSON was swapped, hand-edited, or rebuilt — e.g. someone rewrote the header to change patch metadata and dropped the magic field.
Solutions
- Never hand-edit RVFP files — regenerate with RvfaPatcher.createPatch with the desired metadata
- If metadata must change, rebuild the patch from the source artifacts
- Run RvfaPatcher.verifyPatch() for a structured report of everything wrong (it also checks signature and hashes)
Defensive patterns
Strategy: try-catch
Try / catch
const result = await RvfaPatcher.verifyPatch(buf); // catches header errors AND checks signature/hashes
if (result.errors.length > 0) {
// reject with the full defect report; do not call parsePatchHeader at all
} else {
const header = RvfaPatcher.parsePatchHeader(buf); // now safe
} Prevention
- Treat patches as immutable artifacts — regenerate instead of editing headers in place
- Route untrusted patches through verifyPatch(), which reports all defects in one structured result
When it happens
Trigger: `parsePatchHeader` on a file whose first 12 bytes are genuine but whose header JSON was replaced by a rewriter that omitted or renamed the magic field; spliced/concatenated patches; corruption that spared the preamble.
Common situations: Editing patch headers in place to bump patchVersion or retarget an appliance; partially applied binary edits; malformed patches from non-library tooling.
Related errors
- Invalid RVFP magic
- Buffer too small for declared header
- Buffer too small for RVFP preamble
- Unsupported RVFP version
- frozen human eval hash mismatch — set has drifted
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/a6e83e4f67cc214e.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts:199
header.signedBy = opts.signedBy;
}
const hJson = Buffer.from(JSON.stringify(header), 'utf-8');
const magic = Buffer.from('RVFP');
const ver = Buffer.alloc(4); ver.writeUInt32LE(RVFP_VERSION, 0);
const hLen = Buffer.alloc(4); hLen.writeUInt32LE(hJson.length, 0);
return Buffer.concat([magic, ver, hLen, hJson, payload, sha256B(payload)]);
}
static parsePatchHeader(buf: Buffer): RvfpHeader {
if (buf.length < PRE) throw new Error('Buffer too small for RVFP preamble');
const magic = buf.subarray(0, 4).toString('ascii');
if (magic !== 'RVFP') throw new Error(`Invalid RVFP magic: "${magic}"`);
const ver = buf.readUInt32LE(4);
if (ver !== RVFP_VERSION) throw new Error(`Unsupported RVFP version: ${ver}`);
const hLen = buf.readUInt32LE(8);
if (PRE + hLen > buf.length) throw new Error('Buffer too small for declared header');
const h = JSON.parse(buf.subarray(PRE, PRE + hLen).toString('utf-8')) as RvfpHeader;
if (h.magic !== 'RVFP') throw new Error('RVFP header magic mismatch');
return h;
}
static async verifyPatch(buf: Buffer): Promise<PatchVerifyResult> {
const errors: string[] = [];
let header: RvfpHeader;
try { header = RvfaPatcher.parsePatchHeader(buf); } catch (e) {
const empty: RvfpHeader = {
magic: 'RVFP', version: 0, targetApplianceName: '', targetApplianceVersion: '',
targetSection: '', patchVersion: '', created: '', newSectionSize: 0,
newSectionSha256: '', compression: 'none',
};
return { valid: false, header: empty, errors: [(e as Error).message] };
}
const { start, end, section } = patchData(buf);
if (end < start) {
errors.push('Patch too small: no room for section data and footer');
return { valid: false, header, errors };View on GitHub (pinned to fa13ee4ad6)