{"record":{"id":"c9a044e18d9401d2","repo":"BabylonJS/Babylon.js","slug":"unexpected-end-of-file-before-frame-count","errorCode":null,"errorMessage":"Unexpected end of file before frame count","messagePattern":"Unexpected end of file before frame count","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/BVH/bvhLoader.ts","lineNumber":358,"sourceCode":"    if (!firstLine || firstLine.trim().toUpperCase() !== _HierarchyNode) {\n        throw new Error(\"HIERARCHY expected\");\n    }\n\n    const nodeLine = lines.shift();\n    if (!nodeLine) {\n        throw new Error(\"Unexpected end of file after HIERARCHY\");\n    }\n    const root = ReadNode(lines, nodeLine.trim(), null, context);\n\n    // read motion data\n    const motionLine = lines.shift();\n    if (!motionLine || motionLine.trim().toUpperCase() !== _MotionNode) {\n        throw new Error(\"MOTION expected\");\n    }\n\n    const framesLine = lines.shift();\n    if (!framesLine) {\n        throw new Error(\"Unexpected end of file before frame count\");\n    }\n    const framesTokens = framesLine.trim().split(/[\\s]+/);\n    if (framesTokens.length < 2) {\n        throw new Error(\"Invalid frame count line\");\n    }\n\n    // number of frames\n    const numFrames = parseInt(framesTokens[1]);\n    if (isNaN(numFrames)) {\n        throw new Error(\"Failed to read number of frames.\");\n    }\n    context.numFrames = numFrames;\n\n    // frame time\n    const frameTimeLine = lines.shift();\n    if (!frameTimeLine) {\n        throw new Error(\"Unexpected end of file before frame time\");\n    }","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/BVH/bvhLoader.ts#L340-L376","documentation":"Immediately after the MOTION keyword, a valid BVH file must contain a 'Frames: <count>' line. ReadBvh shifts the next line after MOTION and throws this error when that line is undefined — the text ended right after MOTION with no frame-count line at all. The parser needs the frame count to know how many motion data lines to read, so it cannot continue.","triggerScenarios":"Calling ReadBvh with text that ends exactly at the 'MOTION' line (nothing after it), a file truncated between 'MOTION' and 'Frames:', or passing a string that was sliced/trimmed so trailing lines were dropped before the call.","commonSituations":"Truncated downloads or uploads (file cut off mid-write), server responses cut at a content-length boundary, text editors or scripts that stripped trailing lines, or generating BVH programmatically and forgetting to append the 'Frames:' header and frame data.","solutions":["Verify the file is complete: after MOTION there must be a 'Frames: <n>' line followed by 'Frame Time:' and n data lines; re-download or re-export.","Check file size against the source; a truncated transfer is the most common cause — retry the download.","If generating BVH in code, append the 'Frames: N' and 'Frame Time: t' headers after MOTION.","Log the last lines of the text passed to ReadBvh (text.split('\\n').slice(-5)) to confirm truncation before calling.","Validate with /MOTION\\s*\\n\\s*Frames:\\s*\\d+/ before calling ReadBvh."],"exampleFix":"// before\nMOTION\n// EOF here -> error\n\n// after\nMOTION\nFrames: 60\nFrame Time: 0.033333\n<60 lines of frame data>","handlingStrategy":"validation","validationCode":"function hasFramesHeader(text: string): boolean {\n    return /MOTION\\s*\\n\\s*Frames:\\s*\\d+/i.test(text);\n}\nif (!hasFramesHeader(bvhText)) {\n    throw new Error(\"BVH file truncated before 'Frames:' line\");\n}\nconst skeleton = ReadBvh(bvhText, scene, null, options);","typeGuard":null,"tryCatchPattern":"try {\n    const skeleton = ReadBvh(bvhText, scene, null, options);\n} catch (e) {\n    if (e instanceof Error && e.message.includes(\"before frame count\")) {\n        console.error(\"BVH ends right after MOTION — file truncated\", e);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Verify downloaded file sizes/checksums; truncation between MOTION and Frames: is typical of interrupted transfers.","When generating BVH strings, always append the Frames/Frame Time headers before writing.","Inspect the tail of the file (last 3 lines) in CI before shipping motion assets."],"tags":["bvh","parser","mocap","truncated-file"],"backgroundTag":"bvh-malformed-file","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}