FyroxEngine/Fyrox · error

Failed to import animation

Error message

Failed to import animation: {}

What it means

During glTF animation import, import_animation returned Err for one animation; the loader logs this error with the animation's name and simply skips it, so the resulting model has fewer animations than the source glTF. The actual reason is only in the inner error, which is discarded here.

Solutions

  1. Check the glTF in a validator (gltf-validator / gltf.report) to find the invalid animation channel/sampler
  2. Ensure animated nodes are part of the imported scene graph (skin hierarchy included in the node mapping)
  3. Re-export from the DCC tool with animation sampling enabled and only supported interpolation modes
  4. Log the inner import_animation error (modify code or check for related warnings) to identify the exact failing channel

Example fix

// before: animation silently missing
let model = resource_manager.request::<Model>("character.glb");
// after: confirm animations count matches source
let model = resource_manager.request::<Model>("character.glb");
if let ResourceState::Ok(m) = model.state() {
    assert_eq!(m.animations_ref().len(), expected_animation_count, "glTF animation failed to import");
}
Defensive patterns

Strategy: validation

Validate before calling

// After model load, verify animations count matches the source glTF
let doc = gltf::Gltf::from_slice(&bytes)?;
assert_eq!(doc.animations().len(), model_resource.animations_len(), "animation skipped during import");

Prevention

When it happens

Trigger: import_from_slice loading a glTF whose animation references nodes that couldn't be mapped to handles, samplers/channels with invalid accessors or unsupported interpolation, or empty/ corrupt buffers.

Common situations: glTF animations targeting nodes pruned during import, animations on skeleton bones not shared with the skin, exporters writing non-standard sampler data, or glb files with truncated buffer views.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/723dd446a43e2985. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-impl/src/resource/gltf/animation.rs:295

/// a handle can be looked up using the index of a node within the document. Animations in glTF specify their target
/// nodes by their index within the node list of the document, and these indices need to be translated into handles.
///
/// * `buffers`: A slice containing a list of byte-vectors, one for each buffer in the glTF document.
/// Animations in glTF make reference to data stored in the document's list of buffers by index.
/// This slcie allows an index into the document's list of buffers to be translated into actual bytes of data.
pub fn import_animations(
    doc: &gltf::Document,
    node_handles: &[Handle<Node>],
    graph: &Graph,
    buffers: &[Vec<u8>],
) -> Vec<Animation> {
    let mut imports: Vec<ImportedAnimation> = Vec::with_capacity(doc.animations().len());
    for animation in doc.animations() {
        if let Ok(mut import) = import_animation(&animation, node_handles, buffers) {
            import.simplify_curves();
            imports.push(import);
        } else {
            Log::err(format!(
                "Failed to import animation: {}",
                animation.name().unwrap_or("[Unnamed]")
            ));
        }
    }
    remove_fixed_targets(imports.as_mut_slice(), graph);
    let mut result: Vec<Animation> = Vec::with_capacity(imports.len());
    for import in imports {
        result.push(import.into_animation());
    }
    result
}

fn import_animation(
    animation: &gltf::Animation,
    node_handles: &[Handle<Node>],
    buffers: &[Vec<u8>],
) -> Result<ImportedAnimation> {

View on GitHub (pinned to 76c91aad8e)