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
- 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
- Regenerate the image with RvfaWriter/createDefaultHeader so all required fields and enum values are present
- 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
- 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
- Build headers via createDefaultHeader(profile) so required fields are always present
- Keep enum values within the allowed sets: profile, boot.isolation, models.provider, section.compression
- When exporting headers for external tools, round-trip through validateHeader before writing
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
- Buffer too small to contain declared header
- Buffer too small to contain RVFA preamble
- Failed to parse RVFA header JSON
- Invalid RVFA magic: expected "RVFA", got
- Section " " exceeds buffer bounds
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 sectionsView on GitHub (pinned to fa13ee4ad6)