BabylonJS/Babylon.js · error · Error
Unexpected end of file after HIERARCHY
Error message
Unexpected end of file after HIERARCHY
What it means
ReadBvh parses a BVH motion-capture file line by line and requires the file to begin with a 'HIERARCHY' keyword followed immediately by the root node line (e.g. 'ROOT Hips'). This error is thrown when lines.shift() returns undefined after the HIERARCHY keyword was consumed, meaning the text ended before any root node line was found. The library throws it because the hierarchy section cannot exist without at least one root joint, so parsing must abort.
Source
Thrown at packages/dev/loaders/src/BVH/bvhLoader.ts:346
const { loopMode } = loadingOptions;
scene._blockEntityCollection = !!assetContainer;
const skeleton = new Skeleton("", "", scene);
skeleton._parentContainer = assetContainer;
scene._blockEntityCollection = false;
const context = new LoaderContext(skeleton);
context.loopMode = loopMode;
// read model structure
const firstLine = lines.shift();
if (!firstLine || firstLine.trim().toUpperCase() !== _HierarchyNode) {
throw new Error("HIERARCHY expected");
}
const nodeLine = lines.shift();
if (!nodeLine) {
throw new Error("Unexpected end of file after HIERARCHY");
}
const root = ReadNode(lines, nodeLine.trim(), null, context);
// read motion data
const motionLine = lines.shift();
if (!motionLine || motionLine.trim().toUpperCase() !== _MotionNode) {
throw new Error("MOTION expected");
}
const framesLine = lines.shift();
if (!framesLine) {
throw new Error("Unexpected end of file before frame count");
}
const framesTokens = framesLine.trim().split(/[\s]+/);
if (framesTokens.length < 2) {
throw new Error("Invalid frame count line");
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Check the BVH source file/text is complete: it must contain 'HIERARCHY' followed by a 'ROOT <name>' line; re-download or re-export the file.
- Verify you are not passing an empty string or an error-page body to ReadBvh; log text.length and the first 3 lines before calling.
- Ensure any line-splitting/preprocessing keeps the root line (don't slice the lines array before passing text).
- Confirm the file uses '\n' (or '\r\n') line endings; a lone 'HIERARCHY' with no newline plus binary garbage can still surface as truncation — validate the raw bytes.
- Wrap the load call in try/catch and fall back to a known-good default BVH asset.
Example fix
// before
const text = await fetch(url).then((r) => r.text());
const skeleton = ReadBvh(text, scene, null, options);
// after
const res = await fetch(url);
if (!res.ok) throw new Error(`Failed to load BVH: ${res.status}`);
const text = await res.text();
if (!/HIERARCHY\s+ROOT\s+\S+/i.test(text)) {
throw new Error(`Truncated BVH asset at ${url}`);
}
const skeleton = ReadBvh(text, scene, null, options); Defensive patterns
Strategy: validation
Validate before calling
function isValidBvhHeader(text: string): boolean {
const lines = text.split(/\r?\n/).map((l) => l.trim());
return lines.length >= 2 && lines[0].toUpperCase() === "HIERARCHY" && /^ROOT\s+\S+/i.test(lines[1]);
}
if (!isValidBvhHeader(bvhText)) throw new Error("BVH asset truncated before root node");
const skeleton = ReadBvh(bvhText, scene, null, options); Try / catch
let skeleton: Skeleton;
try {
skeleton = ReadBvh(bvhText, scene, null, options);
} catch (e) {
if (e instanceof Error && e.message.includes("end of file")) {
console.error("BVH file is truncated/incomplete", e);
skeleton = loadFallbackSkeleton(scene);
} else {
throw e;
}
} Prevention
- Check HTTP status and content-length when loading .bvh assets and compare against expected file size.
- Log the first/last lines of the BVH text before parsing to catch truncation early.
- Keep BVH assets in version control or with checksums so corruption is detectable.
- Never pass fetch error-page bodies straight to ReadBvh; gate on res.ok.
When it happens
Trigger: Calling ReadBvh (directly or via the BVH loader) with text that contains only 'HIERARCHY' as its first line and nothing else, e.g. an empty/placeholder BVH string, a file whose content after 'HIERARCHY' was stripped, or text passed without a trailing root line due to faulty preprocessing that split/filtered lines.
Common situations: Downloading a truncated .bvh file (network cut mid-transfer), opening a zero-byte or header-only file, passing an empty string or a CORS/404 HTML error body that coincidentally only reaches the first token, or a build step that inlined only part of the asset.
Related errors
- Unexpected end of file before frame count
- Unexpected end of file: missing OFFSET
- Unexpected end of file: missing CHANNELS
- Unexpected end of file: missing closing brace
- MOTION expected
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/7a2a13286c75045a.
Report an issue: GitHub.