ruvnet/ruflo · error

Buffer too small for declared header

Error message

Buffer too small for declared header

What it means

The preamble's hLen word (offset 8) plus the 12-byte preamble must fit within the buffer. This fires when the declared JSON-header size exceeds what actually arrived — either the hLen field is corrupt (huge value) or the file body is truncated relative to its own length table. The preamble checks (magic/version) already passed, so the head is genuine but the tail is missing.

Solutions

  1. Re-fetch or restore the patch — the file contradicts its own length table
  2. Compare the file size with the producer's recorded size if available
  3. If it reproduces consistently from one producer, check that producer for header-length bugs before blaming transport
Defensive patterns

Strategy: validation

Validate before calling

const hLen = buf.readUInt32LE(8);
if (12 + hLen > buf.length) {
  throw new Error('Patch header truncated in transit — re-download');
}

Try / catch

const result = await RvfaPatcher.verifyPatch(buf); // collects header errors in result.errors
if (result.errors.length > 0) {
  // reject with the structured report instead of letting parsePatchHeader throw
}

Prevention

When it happens

Trigger: `parsePatchHeader(buf)` where readUInt32LE(8) yields a value with 12 + hLen > buf.length: a partially downloaded patch that got the preamble but not all header bytes, or corruption that scrambled the hLen word.

Common situations: Interrupted transfer with a content-length mismatch; files truncated by quota enforcement or sync tools; a producer bug writing wrong header lengths (rare — reproduce from the same source to rule out).

Related errors


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

Appendix: source

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

      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] };
    }
    const { start, end, section } = patchData(buf);
    if (end < start) {

View on GitHub (pinned to fa13ee4ad6)