DioxusLabs/dioxus · error

Failed to get asset manager

Error message

Failed to get asset manager

What it means

Android-only panic in the asset resolver: it attaches the current thread to the JVM and calls the JNI getAssets method on the Activity context to obtain the Java AssetManager. The expect fires when that JNI call fails - most commonly because ndk-context was never initialized (code running outside a real Android app) or the JVM attach/context is unusable.

Source

Thrown at packages/asset-resolver/src/native.rs:278

            return std::fs::read(path).ok();
        }
    }

    use std::ptr::NonNull;

    let ctx = ndk_context::android_context();
    let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
    let mut env = vm.attach_current_thread().unwrap();

    // Query the Asset Manager
    let asset_manager_ptr = env
        .call_method(
            unsafe { jni::objects::JObject::from_raw(ctx.context().cast()) },
            "getAssets",
            "()Landroid/content/res/AssetManager;",
            &[],
        )
        .expect("Failed to get asset manager")
        .l()
        .expect("Failed to get asset manager as object");

    unsafe {
        let asset_manager =
            ndk_sys::AAssetManager_fromJava(env.get_native_interface(), *asset_manager_ptr);

        let asset_manager = ndk::asset::AssetManager::from_ptr(
            NonNull::new(asset_manager).expect("Invalid asset manager"),
        );

        let cstr = std::ffi::CString::new(normalized).unwrap();

        let mut asset = asset_manager.open(&cstr)?;
        Some(asset.buffer().unwrap().to_vec())
    }
}

View on GitHub (pinned to 393d190a80)

Solutions

  1. Run asset-touching code only inside a real Android app launched from an Activity (dx serve/build for Android)
  2. Initialize ndk_context in custom JNI entry points before any asset code runs
  3. Ensure debug assets are pushed so the /data/local/tmp/dx fast path serves them before JNI is reached
  4. Gate host tests with #[cfg(not(target_os = "android"))] or mock the asset layer

Example fix

// before
#[test]
fn reads_config() { let bytes = load_asset("/assets/config.json"); }

// after
#[cfg(target_os = "android")]
#[test]
fn reads_config() { let bytes = load_asset("/assets/config.json"); }
Defensive patterns

Strategy: validation

Validate before calling

// Only exercise Android asset paths inside a real Android app
#[cfg(target_os = "android")]
fn load_bytes(path: &str) -> Option<Vec<u8>> { /* touches JNI asset manager */ }

#[cfg(not(target_os = "android"))]
fn load_bytes(_path: &str) -> Option<Vec<u8>> { None }

Prevention

When it happens

Trigger: Asset resolution reaching to_java_load_asset in a process without a valid Android context: plain cargo test/host unit tests touching asset loading, or custom JNI glue that never called ndk_context::initialize_android_context.

Common situations: Running desktop-style tests locally that hit asset!() code paths; debug builds where the asset is missing from the /data/local/tmp/dx/ cache so the JNI fallback is hit; custom entry points bypassing the dioxus/wry Android launcher.

Related errors


AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16). Data as JSON: /api/errors/fcc6ad8ee9160d81. Report an issue: GitHub.