How to Debug Pumpkin-MC/Pumpkin Code: Essential Techniques for Rust Developers
Debug Pumpkin-MC by configuring the RUST_LOG environment variable for granular tracing, attaching LLDB to the async Tokio runtime, and inspecting packet serialization logic in pumpkin-protocol/src/serial/ while ensuring RUST_BACKTRACE=full captures complete panic traces.
Pumpkin-MC is a high-performance Minecraft server implementation written in Rust. Its architecture splits functionality across independent workspace crates—including pumpkin-protocol for network packets and pumpkin-world for chunk simulation—making targeted debugging essential for resolving issues in this asynchronous codebase.
Understand the Crate Architecture
Before debugging, map your issue to the correct crate. Pumpkin-MC organizes functionality into distinct modules:
pumpkin– Core server loop and world management. Key files includepumpkin/src/world/weather.rsfor weather cycles andpumpkin/src/server.rsfor the mainServerinitialization.pumpkin-protocol– Minecraft packet encoding/decoding. Inspectpumpkin-protocol/src/packet.rsfor the central packet enum andpumpkin-protocol/src/serial/for binary serializers.pumpkin-world– Chunk loading and world data structures. The tick scheduler resides inpumpkin-world/src/tick/scheduler.rs, while Anvil I/O logic lives inpumpkin-world/src/world_info/anvil.rs.pumpkin-plugin-api– Plugin lifecycle and scheduler. The entry point ispumpkin-plugin-api/src/lib.rs, with logging utilities inpumpkin-plugin-api/src/logging.rs.pumpkin-config– TOML configuration parsing, includingpumpkin-config/src/server_links.rsfor server link validation.pumpkin-inventory– Player inventory logic, specificallypumpkin-inventory/src/player/player_inventory.rs.
The server initializes in pumpkin/src/server.rs, loading configurations, initializing the world, and starting the async networking task before entering the tick scheduler.
Configure Logging and Tracing
Pumpkin-MC uses the log crate with env_logger for runtime diagnostics. Control verbosity via the RUST_LOG environment variable:
# Enable debug output for all crates
RUST_LOG=debug cargo run --release
Target specific modules to reduce noise:
RUST_LOG=pumpkin=debug,pumpkin_protocol=debug cargo run
The codebase emits diagnostic messages using macros like log::debug! and log::error!. For example, the protocol crate logs deserialization failures:
log::error!("Failed to deserialize packet: {}", err);
If a module remains silent, verify the crate name uses underscores instead of hyphens in the filter (e.g., pumpkin_protocol not pumpkin-protocol).
Essential Debugging Techniques for Async Rust
Because Pumpkin-MC runs on the Tokio runtime, bugs often surface under concurrent load. Apply these techniques based on the failure mode:
Add debug! statements for quick inspection
Insert temporary logging to inspect values inside functions:
log::debug!("Chunk {} loaded, {} entities", pos, entities.len());
Run targeted unit tests
Isolate components like packet codecs without starting the full server:
cargo test --package pumpkin-protocol
Inspect macro-generated code
Packet definitions use heavy macro codegen. Expand them for inspection:
cargo expand --package pumpkin-codegen
Attach a native debugger
Step through async tasks or watch for panics using LLDB or GDB:
rustup run stable lldb target/debug/pumpkin
Enable full backtraces
Rust backtraces are truncated by default. Capture the full stack on panic:
RUST_BACKTRACE=full cargo run
Profile async performance
Enable the tokio-console feature flag in Cargo.toml to detect task deadlocks or long-running operations in the scheduler.
Use filesystem watches
Detect config reload bugs by auto-rebuilding on changes:
cargo watch -x run
Debug Packet Serialization and Network Issues
Packet handling failures typically originate in pumpkin-protocol. When a client disconnects with a serialization error:
- Enable protocol-level logging:
RUST_LOG=pumpkin_protocol=debug - Examine raw bytes logged by
serializer::write_packetinpumpkin-protocol/src/serial/serializer.rs - Compare the byte sequence against the official Minecraft protocol specification
- Check
pumpkin-protocol/src/serial/deserializer.rsfor offset errors in variable-length integer parsing
If packet structs appear malformed, use cargo expand on the pumpkin-codegen package to verify the generated code in pumpkin-codegen/src/wit/packet_mapping.rs matches your expectations.
Troubleshoot World Ticks and Chunk Loading
World simulation bugs—such as chunks failing to load—stem from the async I/O layer or coordinate calculation errors.
Add debug! statements around the chunk loading path in pumpkin-world/src/world.rs. Verify that ChunkPos calculations in pumpkin/src/world/portal/mod.rs produce valid region file coordinates. If Anvil files fail to parse, inspect the file path construction in pumpkin-world/src/world_info/anvil.rs to ensure region filenames match the expected r.x.z.mca format.
The tick scheduler in pumpkin-world/src/tick/scheduler.rs drives all world updates. If the server hangs, attach a debugger to this module to verify the tick loop isn't blocked by synchronous I/O operations.
Investigate Plugin API Failures
Plugins interact through pumpkin-plugin-api. When a plugin panics or deadlocks:
- Check the scheduler logs in
pumpkin_plugin_api::schedulerfor task execution traces - Verify the plugin's
on_tickimplementation usestokio::spawnfor long-running work to avoid blocking the main tick thread - Ensure the plugin uses the API logger defined in
pumpkin-plugin-api/src/logging.rsrather than standard print statements
Step-by-Step Example: Debugging Player Login Crashes
Consider a crash occurring when players attempt to join. Follow this procedure:
First, enable verbose logging for networking and world systems:
RUST_LOG=pumpkin_protocol=debug,pumpkin_world=debug cargo run --release
Next, add a targeted debug statement in pumpkin/src/player/mod.rs to inspect the login packet fields:
log::debug!(
"Player {} attempting login from {} (protocol version {})",
self.username, addr, packet.protocol_version
);
When the server panics, the backtrace points to pumpkin-protocol::packet::handle_login. Cross-reference the logged protocol version and username against the packet specification to identify mismatched field types or incorrect packet IDs in pumpkin-protocol/src/packet.rs.
Summary
- Structure first: Map your bug to the correct crate—
pumpkin-protocolfor network issues,pumpkin-worldfor chunk errors, orpumpkin-plugin-apifor extension crashes. - Log strategically: Use
RUST_LOG=pumpkin_protocol=debugto isolate specific modules without console spam. - Handle async complexity: Attach LLDB to the Tokio runtime and enable
RUST_BACKTRACE=fullto trace panics across task boundaries. - Verify generated code: Use
cargo expandonpumpkin-codegenwhen packet structs behave unexpectedly. - Inspect serialization: Check
pumpkin-protocol/src/serial/serializer.rsanddeserializer.rsfor protocol mismatches.
Frequently Asked Questions
How do I enable debug logging for specific Pumpkin-MC crates?
Set the RUST_LOG environment variable using the crate name with underscores. For example, use RUST_LOG=pumpkin_protocol=debug for packet handling or RUST_LOG=pumpkin_world=debug for chunk operations. Run the server with RUST_LOG=debug cargo run to capture all crates at once.
Why is my Pumpkin server crashing during player login?
Login crashes typically indicate packet deserialization failures in pumpkin-protocol/src/serial/deserializer.rs. Enable RUST_LOG=pumpkin_protocol=debug to log raw packet bytes, then compare them against the Minecraft protocol specification. Add debug logging to pumpkin/src/player/mod.rs to inspect the protocol version and username fields before the crash occurs.
How can I inspect macro-generated packet code in Pumpkin?
Pumpkin uses macros extensively for packet definitions in the pumpkin-codegen crate. Install cargo-expand and run cargo expand --package pumpkin-codegen to view the generated Rust code in pumpkin-codegen/src/wit/packet_mapping.rs. This reveals the actual struct definitions and trait implementations produced at compile time.
What is the best way to debug async task deadlocks in Pumpkin-MC?
Enable the tokio-console feature flag in the workspace Cargo.toml to monitor task execution in real-time. For post-mortem analysis, run the server under LLDB with rustup run stable lldb target/debug/pumpkin, set breakpoints in pumpkin-world/src/tick/scheduler.rs, and inspect task states when the server hangs. Ensure plugin code in pumpkin-plugin-api uses tokio::spawn for asynchronous operations to avoid blocking the tick loop.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →