{"record":{"id":"056f9c95766bcdd2","repo":"ruvnet/ruflo","slug":"failed-to-parse-rvfa-header-json","errorCode":null,"errorMessage":"Failed to parse RVFA header JSON","messagePattern":"Failed to parse RVFA header JSON","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/rvfa-format.ts","lineNumber":346,"sourceCode":"\n    // Header length\n    const headerLen = buf.readUInt32LE(MAGIC_SIZE + VERSION_SIZE);\n    if (headerLen > MAX_HEADER_JSON_SIZE) {\n      throw new Error(\n        `Header JSON exceeds maximum size (${headerLen} > ${MAX_HEADER_JSON_SIZE})`,\n      );\n    }\n    if (PREAMBLE_SIZE + headerLen > buf.length) {\n      throw new Error('Buffer too small to contain declared header');\n    }\n\n    // Parse header JSON\n    const headerSlice = buf.subarray(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLen);\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(headerSlice.toString('utf-8'));\n    } catch {\n      throw new Error('Failed to parse RVFA header JSON');\n    }\n\n    if (!validateHeader(parsed)) {\n      throw new Error('RVFA header failed validation');\n    }\n    const header = parsed as RvfaHeader;\n\n    // Bounds-check every section offset\n    const totalSize = buf.length;\n    for (const sec of header.sections) {\n      if (sec.offset < 0 || sec.size < 0) {\n        throw new Error(`Section \"${sec.id}\" has negative offset or size`);\n      }\n      if (sec.offset + sec.size > totalSize - SHA256_SIZE) {\n        throw new Error(\n          `Section \"${sec.id}\" extends beyond buffer ` +\n            `(offset=${sec.offset}, size=${sec.size}, bufLen=${totalSize})`,\n        );","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/rvfa-format.ts#L328-L364","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before — opaque parse failure inside fromBuffer\nconst reader = RvfaReader.fromBuffer(buf);\n\n// after — surface exactly what's in the header region first\nconst headerLen = buf.readUInt32LE(8);\nconst slice = buf.subarray(12, 12 + headerLen).toString('utf8');\nJSON.parse(slice); // throws with position info pointing at the bad bytes","handlingStrategy":"try-catch","validationCode":"const headerLen = buf.readUInt32LE(8);\nconst slice = buf.subarray(12, 12 + headerLen).toString('utf8');\ntry { JSON.parse(slice); } catch {\n  console.error('header not JSON, first bytes:', slice.slice(0, 80));\n  throw new Error('refusing to parse: header region corrupt');\n}","typeGuard":null,"tryCatchPattern":"try {\n  reader = RvfaReader.fromBuffer(buf);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Failed to parse RVFA header JSON') {\n    // dump subarray(12, 12+readUInt32LE(8)) to find where JSON breaks\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["rvfa","json-parse","binary-format","corruption"],"backgroundTag":"invalid-json-parse","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}