ruvnet/ruflo · error · Error

Invalid RVFP magic: "${magic}"

Error message

Invalid RVFP magic: "${magic}"

What it means

Thrown by parsePatchHeader() when the first 4 bytes of the buffer are not the ASCII string "RVFP". The buffer is long enough to pass the preamble-size check, but its magic bytes identify it as something other than an RVFP patch. This is the format-identity guard that runs after the length check and before the version check.

Source

Thrown at v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts:193

      created: new Date().toISOString(), newSectionSize: payload.length,
      newSectionSha256: sha256(payload), compression: comp,
    };
    if (opts.privateKey && opts.signedBy) {
      const signable = Buffer.concat([Buffer.from(canonicalJson(header), 'utf-8'), payload]);
      header.signature = edSign(signable, opts.privateKey);
      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',
      };

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Confirm the input is an RVFP patch produced by RvfaPatcher.createPatch().
  2. If the file is gzipped on disk, gunzip it to a Buffer before parsing.
  3. Validate the magic bytes (buf.subarray(0,4).equals(Buffer.from('RVFP'))) before calling.
  4. Re-download or regenerate the patch if the file content is wrong.

Example fix

// before
const header = RvfaPatcher.parsePatchHeader(buf);

// after
if (buf.subarray(0, 4).toString('ascii') !== 'RVFP') {
  throw new Error('Input is not an RVFP patch (bad magic)');
}
const header = RvfaPatcher.parsePatchHeader(buf);
Defensive patterns

Strategy: validation

Validate before calling

function hasRvfpMagic(buf: Buffer): boolean {
  return buf.length >= 4 && buf.subarray(0, 4).toString('ascii') === 'RVFP';
}

Type guard

function isRvfpBuffer(buf: unknown): buf is Buffer {
  return Buffer.isBuffer(buf) && buf.length >= 4 && buf.subarray(0, 4).toString('ascii') === 'RVFP';
}

Try / catch

try {
  const header = RvfaPatcher.parsePatchHeader(buf);
} catch (e) {
  if (/Invalid RVFP magic/.test((e as Error).message)) {
    throw new Error('Input is not an RVFP patch; check that you passed a .rvfp, not a .rvfa');
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a non-patch buffer (e.g. an RVFA appliance, a gzip stream, a JSON document, or random bytes) to parsePatchHeader/applyPatch/verifyPatch. The first 4 bytes happen not to be 0x52 0x56 0x46 0x50 ('R','V','F','P').

Common situations: Swapping a .rvfa appliance file for a .rvfp patch file in a deploy pipeline; feeding a gzipped patch without first gunzipping; reading a file that was overwritten by a different tool.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/bedb85984a2cfa2f. Report an issue: GitHub.