ruvnet/ruflo · error

Section " " exceeds buffer bounds

Error message

Section "${id}" exceeds buffer bounds

What it means

extractSection(id) re-checks at read time that sec.offset + sec.size <= buf.length - 32, even though fromBuffer already validated this. It fires when the buffer shrank between construction and extraction — e.g. the caller passed a subarray/truncated copy — or when a RvfaReader was somehow constructed without full validation. It is defense-in-depth against reading past the data region into the SHA256 footer.

Solutions

  1. Always obtain readers via RvfaReader.fromBuffer(buf) or await RvfaReader.fromFile(path) — both run the full validation pass
  2. Don't share or mutate the buffer you passed to fromBuffer; the reader retains a reference (subarray shares memory)
  3. If you must revalidate, rebuild the reader from the original full buffer rather than patching offsets
  4. Add an assertion on buf.length before extractSection in hot paths to catch early buffer swaps

Example fix

// before — reusing a reader after truncating the source buffer
const reader = RvfaReader.fromBuffer(buf);
buf = buf.subarray(0, 1000); // reader still points at original, sizes now wrong
reader.extractSection('kernel');

// after — rebuild the reader from the bytes you actually have
const reader = RvfaReader.fromBuffer(buf);
// ... later, if buf changed:
const fresh = RvfaReader.fromBuffer(currentBuf);
Defensive patterns

Strategy: validation

Validate before calling

const sec = reader.getSections().find((s) => s.id === id);
if (!sec || sec.offset + sec.size > buf.length - 32) {
  throw new Error('section would read past data region — buffer changed');
}

Try / catch

try { const data = reader.extractSection(id); }
catch (e) {
  if (/exceeds buffer bounds/.test(String((e as Error).message))) {
    // rebuild the reader from the full original buffer
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling extractSection after the reader's underlying buffer was replaced or the reader was built via a path that skipped validation; or holding a reader over a Buffer that a debugging step reallocated. In normal use (fromBuffer/fromFile) this is unreachable — seeing it means the reader instance was constructed unusually or the buffer was mutated.

Common situations: Test code constructing RvfaReader-like objects directly; buffer pooling/copying bugs where a smaller buffer is handed to an existing reader; memory-pressure 'optimizations' that slice buffers in place.

Related errors


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

Appendix: source

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

  /** List all sections declared in the header. */
  getSections(): RvfaSection[] {
    return this.header.sections;
  }

  /**
   * Extract and decompress a section by its id.
   *
   * @param id  The section identifier (e.g. 'kernel', 'runtime').
   * @returns   The decompressed section payload.
   */
  extractSection(id: string): Buffer {
    const sec = this.header.sections.find((s) => s.id === id);
    if (!sec) {
      throw new Error(`Section "${id}" not found`);
    }

    if (sec.offset + sec.size > this.buf.length - SHA256_SIZE) {
      throw new Error(`Section "${id}" exceeds buffer bounds`);
    }

    const raw = this.buf.subarray(sec.offset, sec.offset + sec.size);

    if (sec.compression === 'gzip') {
      return gunzipSync(raw);
    }
    if (sec.compression === 'zstd') {
      // zstd not natively supported — attempt gzip fallback (mirrors writer)
      try {
        return gunzipSync(raw);
      } catch {
        throw new Error(
          'zstd decompression is not supported in this environment',
        );
      }
    }

View on GitHub (pinned to fa13ee4ad6)