ruvnet/ruflo · error
Failed to parse RVFA header JSON
Error message
Failed to parse RVFA header JSON
What it means
Thrown when the byte range [12, 12+headerLen) of the RVFA buffer exists (the length check at rvfa-format.ts:337 passed) but does not parse as JSON. The bytes are present yet their content is not valid UTF-8 JSON — either the header region is corrupted, or headerLen is subtly wrong so the slice starts mid-JSON or bleeds into binary section data.
Solutions
- Dump the slice and inspect it: buf.subarray(12, 12 + buf.readUInt32LE(8)).toString('utf8') — partial JSON means headerLen is wrong; binary garbage means offsets shifted
- Regenerate the appliance image with a current RvfaWriter — the header also carries section offsets, so patching it by hand is fragile
- If you control the writer, ensure it serializes with Buffer.from(JSON.stringify(header), 'utf8') (no BOM) and stores that exact byte length
- Compare the writer and reader package versions; a layout change across versions produces exactly this off-by-N slicing
Example fix
// before — opaque parse failure inside fromBuffer
const reader = RvfaReader.fromBuffer(buf);
// after — surface exactly what's in the header region first
const headerLen = buf.readUInt32LE(8);
const slice = buf.subarray(12, 12 + headerLen).toString('utf8');
JSON.parse(slice); // throws with position info pointing at the bad bytes Defensive patterns
Strategy: try-catch
Validate before calling
const headerLen = buf.readUInt32LE(8);
const slice = buf.subarray(12, 12 + headerLen).toString('utf8');
try { JSON.parse(slice); } catch {
console.error('header not JSON, first bytes:', slice.slice(0, 80));
throw new Error('refusing to parse: header region corrupt');
} Try / catch
try {
reader = RvfaReader.fromBuffer(buf);
} catch (e) {
if (e instanceof Error && e.message === 'Failed to parse RVFA header JSON') {
// dump subarray(12, 12+readUInt32LE(8)) to find where JSON breaks
}
throw e;
} Prevention
- Generate and read images with the same package version so header layout can't drift
- Transfer .rvfa files in binary mode only; never open them in text editors
- Keep writer's JSON serialization and length write adjacent in code so they can't diverge
When it happens
Trigger: RvfaReader.fromBuffer/fromFile on a file where bytes 12..12+headerLen are not valid JSON: headerLen off by a few bytes so the slice cuts the JSON short or includes section bytes; the header was written as UTF-16 or with a BOM; the file was byte-edited or re-encoded after generation.
Common situations: A writer/reader version mismatch that shifts the preamble layout; text editors or transfer pipelines that 'helpfully' re-encode the file; custom scripts rewriting the preamble with wrong offsets; archive corruption that happens to keep total size plausible.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse RVFA header JSON
- Buffer too small to contain declared header
- Buffer too small to contain RVFA preamble
- Invalid RVFA magic: expected "RVFA", got
- RVFA header failed validation
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/056f9c95766bcdd2.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/appliance/rvfa-format.ts:346
// Header length
const headerLen = buf.readUInt32LE(MAGIC_SIZE + VERSION_SIZE);
if (headerLen > MAX_HEADER_JSON_SIZE) {
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})`,
);View on GitHub (pinned to fa13ee4ad6)