bevyengine/bevy
Debugging
How to find what's wrong, both when developing Bevy itself and when shipping a game on top of it.
The official docs at docs/debugging.md and docs/profiling.md cover the basics. This page is the practical companion.
Logs
Bevy uses tracing for both events and spans. The integration is in bevy_log. Filtering follows the standard RUST_LOG syntax:
# Everything at info, but bevy_render at debug
RUST_LOG=info,bevy_render=debug cargo run --example 3d_scene
# Trace level for a specific crate
RUST_LOG=bevy_ecs=trace cargo run
# Multiple filters
RUST_LOG=warn,bevy_app=info,bevy_asset=debug cargo runbevy_log registers a tracing-subscriber formatter at startup; LogPlugin::default() honors RUST_LOG, or you can override the filter directly:
App::new().add_plugins(DefaultPlugins.set(LogPlugin {
filter: "bevy_render=debug,wgpu=warn".into(),
level: bevy::log::Level::INFO,
..default()
}));Tracing spans and Tracy
Bevy instruments hot paths with tracing spans. Enable the trace cargo feature to record them at runtime:
cargo run --features trace,trace_tracy --example many_cubestrace_tracy integrates with Tracy via tracy-client. Running Tracy's UI alongside the example gives a per-frame waterfall.
Other tracing backends are available behind cargo features in crates/bevy_log/Cargo.toml:
trace_chrome— emits a Chromechrome://tracingJSON file.tracing-tracy— Tracy backend.trace_tracy_memory— memory allocation hooks.
Profilers
docs/profiling.md walks through:
- CPU profiling —
cargo flamegraph,samply,cargo-instrumentson macOS. - GPU profiling — RenderDoc, Xcode's GPU debugger, RGP for AMD, Nsight for NVIDIA.
For Bevy-specific GPU work, the render graph nodes are individually labeled (search crates/bevy_core_pipeline/src/ for RenderLabel enums) and show up by name in any GPU debugger that supports labeled passes.
Built-in dev tools
The bevy_dev_tools crate provides:
FpsOverlayPlugin— on-screen FPS counter.StateInspectorPlugin(whendevfeatures are on) — visual inspector forStates.fps_overlayexample — minimal demo.
The diagnostics framework in bevy_diagnostic lets you add custom counters that show up in the same overlay or in LogDiagnosticsPlugin's console output.
The Bevy Remote Protocol (BRP)
The most powerful debugging surface is the BRP. Enable the bevy_remote cargo feature, add RemotePlugin and RemoteHttpPlugin, and a JSON-RPC interface comes online on http://127.0.0.1:15702.
You can then query the world from anywhere:
curl -X POST http://127.0.0.1:15702 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"bevy/list"}'This is the foundation of the upcoming inspector; it's also the easiest way to debug a running game without rebuilding.
Common errors and how to diagnose them
"the trait bound T: Component is not satisfied"
Forgot #[derive(Component)]. Re-derive on the type and ensure it's Send + Sync + 'static.
"Resource X does not exist"
A system used Res<X> but no plugin inserted X. Either add app.insert_resource(X::default()) or guard the system with if_resource_exists::<X> / Option<Res<X>>.
"Query parameters are mutually conflicting"
Two parameters of the same system want the same component with conflicting access (e.g., two Query<&mut T> on the same archetype). Either use one query with Or<...> filters, or split into separate systems. The compiler error usually pinpoints the conflict.
"Schedule X is not registered"
Most often: forgot to call app.init_schedule(MyLabel) or used a label whose schedule was added in a SubApp other than the main one.
Renders to a blank window
Almost always either (a) no camera spawned, (b) camera and entity not on the same RenderLayers, (c) entity culled by Visibility/ViewVisibility, or (d) a missing MeshMaterial3d/MeshMaterial2d component.
"wgpu validation error" on startup
GPU adapter doesn't support the requested features. Set the WGPU_BACKEND env var (e.g. WGPU_BACKEND=vulkan) or look at the printed adapter info to see which limit was exceeded.
Catching panics
bevy_app::PanicHandlerPlugin (in DefaultPlugins) installs a panic hook that prints a stack trace via tracing::error!. On Wasm, panics surface in the browser console. The panic handler is in crates/bevy_app/src/panic_handler.rs.
For production builds, set the BEVY_BACKTRACE=full env var to get unwound stack traces with symbols.
Inspecting schedules
The schedule graph is queryable at runtime:
fn dump_schedule(schedules: Res<Schedules>) {
for (label, schedule) in schedules.iter() {
println!("{:?}: {} systems", label, schedule.systems().count());
}
}For a richer view, use bevy-inspector-egui (third-party). The BRP also exposes schedule introspection for tooling.
When all else fails
- Check
target/debug/build/<crate>-<hash>/outputfor build-script logs. - Run
cargo clean -p <crate>if you suspect stale artifacts. - Try the
bevy_dev_toolspicking_debugexample to confirm picking events route correctly. - Ask in
#dev-helpon the Bevy Discord with a minimal reproduction.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.