ruvnet/ruflo · error

Section " " extends beyond buffer (offset= , size= …

Error message

Section "${sec.id}" extends beyond buffer (offset=${sec.offset}, size=${sec.size}, bufLen=${totalSize})

What it means

A section in the header declares offset + size extending past buf.length - 32 (the reader reserves the last 32 bytes for the SHA256 footer). Unlike the constructor-time 'Buffer too small' check, the preamble and header parsed fine — the section data region itself is short. Almost always a truncated file: the header was written first, the payload didn't fully land.

Solutions

  1. Compare file size with the source and re-transfer — compute expected size as last section's offset + size + 32 from the header
  2. If self-assembling buffers, ensure every staged section's data is actually concatenated in build() before the 32-byte footer
  3. Run the image through its integrity check (verify() / footer SHA256) to confirm truncation before re-downloading
  4. Check free disk space at the write location — ENOSPC often surfaces later as this read error

Example fix

// before — sections described but payload omitted
const out = Buffer.concat([preamble, headerJson, sec0, footer]); // sec1 missing

// after — concatenate every staged section, then footer
const out = Buffer.concat([preamble, headerJson, ...staged.map((s) => s.data), footer]);
Defensive patterns

Strategy: validation

Validate before calling

const headerLen = buf.readUInt32LE(8);
const header = JSON.parse(buf.subarray(12, 12 + headerLen).toString('utf8'));
const maxEnd = Math.max(0, ...header.sections.map((s: any) => s.offset + s.size));
if (maxEnd > buf.length - 32) throw new Error('image truncated — re-fetch');

Try / catch

try { reader = RvfaReader.fromBuffer(buf); }
catch (e) {
  if (/extends beyond buffer/.test(String((e as Error).message))) {
    // re-download / rebuild; the bytes after the header are short
  }
  throw e;
}

Prevention

When it happens

Trigger: RvfaReader.fromBuffer/fromFile where the largest section (typically 'kernel' or 'runtime') runs past the end — e.g. an image cut off mid-download, or a buffer assembled by concatenating preamble+header with only part of the section data before the footer.

Common situations: Partial downloads (interrupted curl/scp); CI artifacts capped by max-size limits; disk exhaustion during image write; tests that build a header describing N sections but concatenate only N-1 payloads.

Related errors


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

Appendix: source

Thrown at v3/@claude-flow/cli/src/appliance/rvfa-format.ts:361

    try {
      parsed = JSON.parse(headerSlice.toString('utf-8'));
    } catch {
      throw new Error('Failed to parse RVFA header JSON');
    }

    if (!validateHeader(parsed)) {
      throw new Error('RVFA header failed validation');
    }
    const header = parsed as RvfaHeader;

    // Bounds-check every section offset
    const totalSize = buf.length;
    for (const sec of header.sections) {
      if (sec.offset < 0 || sec.size < 0) {
        throw new Error(`Section "${sec.id}" has negative offset or size`);
      }
      if (sec.offset + sec.size > totalSize - SHA256_SIZE) {
        throw new Error(
          `Section "${sec.id}" extends beyond buffer ` +
            `(offset=${sec.offset}, size=${sec.size}, bufLen=${totalSize})`,
        );
      }
    }

    // Check for overlapping sections
    const sorted = [...header.sections].sort((a, b) => a.offset - b.offset);
    for (let i = 1; i < sorted.length; i++) {
      const prev = sorted[i - 1];
      const curr = sorted[i];
      if (prev.offset + prev.size > curr.offset) {
        throw new Error(
          `Sections "${prev.id}" and "${curr.id}" overlap ` +
            `(${prev.offset}+${prev.size} > ${curr.offset})`,
        );
      }
    }

View on GitHub (pinned to fa13ee4ad6)