{"record":{"id":"115c10877ba52b61","repo":"BabylonJS/Babylon.js","slug":"invalid-or-empty-skeleton-provided","errorCode":null,"errorMessage":"Invalid or empty skeleton provided","messagePattern":"Invalid or empty skeleton provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/serializers/src/BVH/bvhSerializer.ts","lineNumber":23,"sourceCode":"import { Vector3, Quaternion, Matrix } from \"core/Maths/math.vector\";\nimport { Tools } from \"core/Misc/tools\";\nimport { Epsilon } from \"core/Maths/math.constants\";\nimport { type Nullable } from \"core/types\";\n\ninterface IBVHBoneData {\n    bone: Bone;\n    children: IBVHBoneData[];\n    hasPositionChannels: boolean;\n    hasRotationChannels: boolean;\n    positionKeys: IAnimationKey[];\n    rotationKeys: IAnimationKey[];\n}\n\nexport class BVHExporter {\n    public static Export(skeleton: Skeleton, animationNames: string[] = [], frameRate?: number): string {\n        // Validate skeleton\n        if (!skeleton || skeleton.bones.length === 0) {\n            throw new Error(\"Invalid or empty skeleton provided\");\n        }\n\n        // If no animation names provided, use all available animations\n        let animationsToExport = animationNames;\n        if (!animationNames || animationNames.length === 0) {\n            animationsToExport = skeleton.animations.map((anim) => anim.name);\n        }\n\n        // Calculate overall animation range from all specified animations\n        let overallRange: Nullable<AnimationRange> = null;\n        for (const animName of animationsToExport) {\n            const range = skeleton.getAnimationRange(animName);\n            if (range) {\n                overallRange = overallRange ? new AnimationRange(\"animation-range\", Math.min(overallRange.from, range.from), Math.max(overallRange.to, range.to)) : range;\n            }\n        }\n\n        if (!overallRange) {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/serializers/src/BVH/bvhSerializer.ts#L5-L41","documentation":"BVHExporter.Export validates its input before building the BVH motion text: the skeleton must exist and contain at least one bone. Otherwise there is no hierarchy to write and the export is aborted. The message also covers a non-null skeleton with zero bones.","triggerScenarios":"Passing null/undefined to BVHExporter.Export, or a Skeleton instance whose bones array is empty (skeleton created but bones never built, or joints not yet linked).","commonSituations":"Calling export before skeleton.buildFromMesh / before the skeleton is constructed from a mesh; a scene load that silently failed leaving an empty Skeleton; retrieving a skeleton by name from the scene with a typo and getting undefined.","solutions":["Check skeleton && skeleton.bones.length > 0 before calling Export","Ensure the skeleton was built (e.g. from a mesh or importer) and bones are loaded before exporting","Verify the scene/skeleton reference is correct (not undefined from a failed scene.getSkeletonByName)"],"exampleFix":"// before\nconst bvh = BVHExporter.Export(scene.getSkeletonByName(\"rig\")!); // may throw\n// after\nconst skel = scene.getSkeletonByName(\"rig\");\nif (skel && skel.bones.length > 0) {\n    const bvh = BVHExporter.Export(skel);\n}","handlingStrategy":"validation","validationCode":"if (!skeleton || skeleton.bones.length === 0) {\n  throw new Error(`Cannot export BVH: skeleton '${name}' missing or has no bones`);\n}","typeGuard":"function isExportableSkeleton(s: Skeleton | null | undefined): s is Skeleton {\n  return !!s && Array.isArray(s.bones) && s.bones.length > 0;\n}","tryCatchPattern":"try {\n  const bvh = BVHExporter.Export(skeleton);\n} catch (e) {\n  if (String(e.message).includes(\"Invalid or empty skeleton\")) {\n    logger.warn(\"Skipping BVH export: skeleton not built yet\", e);\n  } else throw e;\n}","preventionTips":["Verify skeleton.bones.length > 0 after load and before export","Check scene.getSkeletonByName return value for undefined (typo guard)","Ensure importer/buildFromMesh has completed before exporting"],"tags":["bvh","skeleton","validation","export","animation"],"backgroundTag":"empty-skeleton","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}