ruvnet/ruflo · error · Error

Unsupported RVFP version: ${ver}

Error message

Unsupported RVFP version: ${ver}

What it means

Thrown by parsePatchHeader() when the u32LE version field at offset 4 does not equal RVFP_VERSION (currently 1). The magic check has already passed, so the buffer is structurally an RVFP patch, but it was produced by an incompatible (future or legacy) version of the format. The library refuses to interpret fields it cannot safely decode.

Source

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

    };
    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',
      };
      return { valid: false, header: empty, errors: [(e as Error).message] };
    }

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Recreate the patch with a version of the library whose RVFP_VERSION matches the reader (currently 1).
  2. Upgrade the parsing-side library to match the patch producer's version.
  3. Verify the patch was not corrupted in transit (check the trailing SHA256 footer via verifyPatch).
  4. Do not attempt to hand-edit the version field — the rest of the layout may differ.
Defensive patterns

Strategy: try-catch

Validate before calling

const EXPECTED_RVFP_VERSION = 1;
function rvfpVersionMatches(buf: Buffer): boolean {
  return buf.length >= 8 && buf.readUInt32LE(4) === EXPECTED_RVFP_VERSION;
}

Try / catch

try {
  const header = RvfaPatcher.parsePatchHeader(buf);
} catch (e) {
  if (/Unsupported RVFP version/.test((e as Error).message)) {
    throw new Error('Patch was produced by an incompatible RVFP version; align producer and reader library versions');
  }
  throw e;
}

Prevention

When it happens

Trigger: Parsing a patch created by a newer RvfaPatcher that bumped RVFP_VERSION, or a hand-crafted/test buffer with an arbitrary version field. Also possible if the version bytes are corrupted.

Common situations: Cross-version patch distribution: an appliance built with an older CLI receives a patch from a newer CLI, or vice versa. Edge case: bit-flip corruption of the version field in storage.

Related errors


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