{"record":{"id":"ff500c36eb7f5cce","repo":"moeru-ai/airi","slug":"no-hips-position-track-of-type-vectorkeyframetrack","errorCode":null,"errorMessage":"No Hips.position track of type VectorKeyframeTrack found in animation.","messagePattern":"No Hips\\.position track of type VectorKeyframeTrack found in animation\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui-three/src/composables/vrm/animation.ts","lineNumber":68,"sourceCode":"// Set initial positions for animation\nexport function reAnchorRootPositionTrack(clip: AnimationClip, _vrm: VRMCore) {\n// Get the hips node to re-anchor the root position track\n  const hipNode = _vrm.humanoid?.getNormalizedBoneNode('hips')\n  if (!hipNode) {\n    console.warn('No hips node found in VRM model.')\n    return\n  }\n  hipNode.updateMatrixWorld(true)\n  const defaultHipPos = new Vector3()\n  hipNode.getWorldPosition(defaultHipPos)\n\n  // Calculate the offset from the hips node to the hips's first frame position\n  const hipsTrack = clip.tracks.find(track =>\n    track instanceof VectorKeyframeTrack\n    && track.name === `${hipNode.name}.position`,\n  )\n  if (!(hipsTrack instanceof VectorKeyframeTrack)) {\n    console.warn('No Hips.position track of type VectorKeyframeTrack found in animation.')\n    return\n  }\n\n  const animeHipPos = new Vector3(\n    hipsTrack.values[0],\n    hipsTrack.values[1],\n    hipsTrack.values[2],\n  )\n  const animeDelta = new Vector3().subVectors(animeHipPos, defaultHipPos)\n\n  clip.tracks.forEach((track) => {\n    if (track.name.endsWith('.position') && track instanceof VectorKeyframeTrack) {\n      for (let i = 0; i < track.values.length; i += 3) {\n        track.values[i] -= animeDelta.x\n        track.values[i + 1] -= animeDelta.y\n        track.values[i + 2] -= animeDelta.z\n      }\n    }","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui-three/src/composables/vrm/animation.ts#L50-L86","documentation":"After finding the hips node, reAnchorRootPositionTrack() searches clip.tracks for a VectorKeyframeTrack whose name is exactly `${hipNode.name}.position`. If no such track exists — the animation contains only rotations, or the position track uses a different PropertyBinding name/path — it warns and returns, leaving the root position uncorrected.","triggerScenarios":"Playing an upper-body or idle .vrma that animates only bone quaternion tracks; a clip whose hips position track is bound to the raw (non-normalized) bone name so the normalized hipNode.name does not match; hand-built AnimationClips without a hips position track.","commonSituations":"Mix-and-match of clips from different rigs; three.js track-name formats (node.position vs bones[name].position) after retargeting; upper-body-only animations.","solutions":["Log clip.tracks.map(t => t.name) and compare with the expected `${hipNode.name}.position` binding.","Use a .vrma that actually keyframes hips translation (full-body animations do).","If the track is optional for your clip type, guard with the same check and skip re-anchoring intentionally."],"exampleFix":"// before\nreAnchorRootPositionTrack(clip, vrm) // warns: no hips position track\n\n// after\nconst hips = vrm.humanoid?.getNormalizedBoneNode('hips')\nconst hasHipsPos = !!hips && clip.tracks.some(t => t.name === `${hips.name}.position`)\nif (hasHipsPos) reAnchorRootPositionTrack(clip, vrm)","handlingStrategy":"validation","validationCode":"const hips = vrm.humanoid?.getNormalizedBoneNode('hips')\nconst hasHipsPosTrack = !!hips && clip.tracks.some(t => t.name === `${hips.name}.position`)\nif (!hasHipsPosTrack) { /* rotation-only clip: skip re-anchor */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Classify clips (full-body vs upper-body) before applying root re-anchoring.","Log track names when integrating new .vrma assets to confirm binding format.","Remember re-anchoring is an enhancement; design playback to be correct without it."],"tags":["vrm","animation","keyframe-track","threejs"],"backgroundTag":"missing-animation-track","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}