ruvnet/ruflo · error

Unsupported RVFP version

Error message

Unsupported RVFP version: ${ver}

What it means

The u32 LE version word at offset 4 of an RVFP patch must equal RVFP_VERSION (currently 1). A different value means the patch was produced by a tool with a different format version than this parser — a forward/backward compatibility break — or the version field got corrupted (though bad magic usually trips first).

Solutions

  1. Upgrade the consuming @claude-flow/cli to at least the version that produced the patch (check its changelog for RVFP version bumps)
  2. Or regenerate the patch locally with the current version via RvfaPatcher.createPatch
  3. If both sides claim version 1, suspect corruption — re-transfer the file

Example fix

// before — patch produced by a newer tool
const header = RvfaPatcher.parsePatchHeader(buf); // Unsupported RVFP version: 2

// after — gate on the version word before parsing
const ver = buf.readUInt32LE(4);
if (ver !== 1) throw new Error(`Patch format v${ver} unsupported by this CLI — upgrade or rebuild the patch`);
Defensive patterns

Strategy: validation

Validate before calling

const version = buf.readUInt32LE(4);
if (version !== 1) { // RVFP_VERSION
  throw new Error(`Patch format v${version} unsupported — upgrade @claude-flow/cli or rebuild the patch`);
}

Try / catch

try {
  header = RvfaPatcher.parsePatchHeader(buf);
} catch (e) {
  if (/Unsupported RVFP version/.test(String(e))) {
    // producer/consumer version skew — prompt upgrade or regenerate the patch
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: `parsePatchHeader` on a patch built by a newer @claude-flow/cli whose RVFP_VERSION moved past 1; a mangled file where the version word is garbage; stale cached patches read after a format bump.

Common situations: Producer and consumer machines on different CLI versions; patches fetched from IPFS that were built with a newer release; mixed-version fleets exchanging patches.

Related errors


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

Appendix: 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 fa13ee4ad6)