bevyengine/bevy · error

Bevy must be setup with the #[bevy_main] macro on Android

Error message

Bevy must be setup with the #[bevy_main] macro on Android

What it means

Panics on Android in the asset IO layer when the app entry point was not set up with the #[bevy_main] macro. Android asset loading requires the Bevy android entry shim to initialize the AndroidApp/AssetManager state; without it there is no asset manager to read from.

Source

Thrown at crates/bevy_asset/src/io/android.rs:25

use std::path::Path;

/// [`AssetReader`] implementation for Android devices, built on top of Android's [`AssetManager`].
///
/// Implementation details:
///
/// - All functions use the [`AssetManager`] to load files.
/// - [`is_directory`](AssetReader::is_directory) tries to open the path
/// as a normal file and treats an error as if the path is a directory.
/// - Watching for changes is not supported. The watcher method will do nothing.
///
/// [AssetManager]: https://developer.android.com/reference/android/content/res/AssetManager
pub struct AndroidAssetReader;

impl AssetReader for AndroidAssetReader {
    async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
        let asset_manager = bevy_android::ANDROID_APP
            .get()
            .expect("Bevy must be setup with the #[bevy_main] macro on Android")
            .asset_manager();
        let mut opened_asset = asset_manager
            .open(&CString::new(path.to_str().unwrap()).unwrap())
            .ok_or(AssetReaderError::NotFound(path.to_path_buf()))?;
        let bytes = opened_asset.buffer()?;
        let reader = VecReader::new(bytes.to_vec());
        Ok(reader)
    }

    async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
        let meta_path = get_meta_path(path);
        let asset_manager = bevy_android::ANDROID_APP
            .get()
            .expect("Bevy must be setup with the #[bevy_main] macro on Android")
            .asset_manager();
        let mut opened_asset = asset_manager
            .open(&CString::new(meta_path.to_str().unwrap()).unwrap())
            .ok_or(AssetReaderError::NotFound(meta_path))?;

View on GitHub (pinned to 396ca72708)

Solutions

  1. Declare your main function with #[bevy_main] so the android shim stores the app state
  2. Use bevy's android build setup (bevy_android / cargo-apk or the supported xbuild flow) so the entry macro is active
  3. Verify you are building with the correct android target and entry wiring, not plain fn main
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/bevy_asset/src/io/android.rs:25 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/92f11cc33df21b58. Report an issue: GitHub.