ruvnet/ruflo · error

RVFA header failed validation

Error message

RVFA header failed validation

What it means

The header JSON parsed successfully but failed the exported validateHeader() type-guard (rvfa-format.ts:143-172). That check requires magic === 'RVFA', numeric version >= 1, string name/appVersion/arch/platform/created, profile in {cloud,hybrid,offline}, arrays for sections and capabilities, a well-formed boot object (entrypoint string, args array, env object, isolation enum), a models object with a valid provider, and — critically — every section entry having id/type/sha256 strings, numeric offset/size/originalSize, and compression in {none,gzip,zstd}. Structurally valid JSON that misses any of these is rejected.

Solutions

  1. Parse the header slice yourself (subarray(12, 12+readUInt32LE(8))) and run the exported validateHeader(parsed) — since it is a type-guard, iterate field-by-field to find which requirement fails
  2. Regenerate the image with RvfaWriter/createDefaultHeader so all required fields and enum values are present
  3. If the header was hand-edited, restore enum values to the allowed sets: profile cloud|hybrid|offline, boot.isolation container|microvm|native, models.provider ruvllm|api-vault|hybrid, section.compression none|gzip|zstd
  4. Check every section entry has all six required keys: id, type, offset, size, originalSize, sha256, compression

Example fix

// before — unknown why validation failed
const reader = RvfaReader.fromBuffer(buf);

// after — locate the failing field with the exported guard
const parsed = JSON.parse(buf.subarray(12, 12 + buf.readUInt32LE(8)).toString('utf8'));
if (!validateHeader(parsed)) {
  // check each requirement individually to pinpoint the missing/invalid field
  console.error('bad fields:', Object.entries(parsed).filter(([k, v]) => v === undefined).map(([k]) => k));
}
Defensive patterns

Strategy: validation

Validate before calling

import { validateHeader } from './rvfa-format.js';

const parsed = JSON.parse(buf.subarray(12, 12 + buf.readUInt32LE(8)).toString('utf8'));
if (!validateHeader(parsed)) {
  throw new Error('header failed schema validation — regenerate image');
}

Type guard

// the library exports the guard itself: validateHeader(header: unknown): header is RvfaHeader
import { validateHeader, type RvfaHeader } from './rvfa-format.js';

function asRvfaHeader(v: unknown): RvfaHeader | null {
  return validateHeader(v) ? v : null;
}

Prevention

When it happens

Trigger: RvfaReader.fromBuffer on an image whose header omits a required field (e.g. no 'capabilities' array, boot.isolation misspelled as 'docker', or a section entry missing 'originalSize'). Also produced by third-party tools that emit a lookalike header with different field names or extra/missing keys.

Common situations: Hand-authored or machine-generated headers from external packaging scripts; schema drift between an old writer and a newer reader that added required fields; a header edited to change 'profile' or 'provider' to a value outside the allowed enums.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

      throw new Error(
        `Header JSON exceeds maximum size (${headerLen} > ${MAX_HEADER_JSON_SIZE})`,
      );
    }
    if (PREAMBLE_SIZE + headerLen > buf.length) {
      throw new Error('Buffer too small to contain declared header');
    }

    // Parse header JSON
    const headerSlice = buf.subarray(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLen);
    let parsed: unknown;
    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

View on GitHub (pinned to fa13ee4ad6)