# How to Debug Pumpkin-MC/Pumpkin Code: Essential Techniques for Rust Developers

> Debug Pumpkin-MC Rust code effectively. Learn to use RUST_LOG, LLDB with Tokio, and inspect packet serialization. Capture detailed panic traces with RUST_BACKTRACE=full.

- Repository: [Pumpkin MC/Pumpkin](https://github.com/Pumpkin-MC/Pumpkin)
- Tags: how-to-guide
- Published: 2026-07-23

---

**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 include [`pumpkin/src/world/weather.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin/src/world/weather.rs) for weather cycles and [`pumpkin/src/server.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin/src/server.rs) for the main `Server` initialization.
- **`pumpkin-protocol`** – Minecraft packet encoding/decoding. Inspect [`pumpkin-protocol/src/packet.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-protocol/src/packet.rs) for the central packet enum and `pumpkin-protocol/src/serial/` for binary serializers.
- **`pumpkin-world`** – Chunk loading and world data structures. The tick scheduler resides in [`pumpkin-world/src/tick/scheduler.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-world/src/tick/scheduler.rs), while Anvil I/O logic lives in [`pumpkin-world/src/world_info/anvil.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-world/src/world_info/anvil.rs).
- **`pumpkin-plugin-api`** – Plugin lifecycle and scheduler. The entry point is [`pumpkin-plugin-api/src/lib.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-plugin-api/src/lib.rs), with logging utilities in [`pumpkin-plugin-api/src/logging.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-plugin-api/src/logging.rs).
- **`pumpkin-config`** – TOML configuration parsing, including [`pumpkin-config/src/server_links.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-config/src/server_links.rs) for server link validation.
- **`pumpkin-inventory`** – Player inventory logic, specifically [`pumpkin-inventory/src/player/player_inventory.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-inventory/src/player/player_inventory.rs).

The server initializes in [`pumpkin/src/server.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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:

```bash

# Enable debug output for all crates

RUST_LOG=debug cargo run --release

```

Target specific modules to reduce noise:

```bash
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:

```rust
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:

```rust
log::debug!("Chunk {} loaded, {} entities", pos, entities.len());

```

**Run targeted unit tests**

Isolate components like packet codecs without starting the full server:

```bash
cargo test --package pumpkin-protocol

```

**Inspect macro-generated code**

Packet definitions use heavy macro codegen. Expand them for inspection:

```bash
cargo expand --package pumpkin-codegen

```

**Attach a native debugger**

Step through async tasks or watch for panics using LLDB or GDB:

```bash
rustup run stable lldb target/debug/pumpkin

```

**Enable full backtraces**

Rust backtraces are truncated by default. Capture the full stack on panic:

```bash
RUST_BACKTRACE=full cargo run

```

**Profile async performance**

Enable the `tokio-console` feature flag in [`Cargo.toml`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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:

```bash
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:

1. Enable protocol-level logging: `RUST_LOG=pumpkin_protocol=debug`
2. Examine raw bytes logged by `serializer::write_packet` in [`pumpkin-protocol/src/serial/serializer.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-protocol/src/serial/serializer.rs)
3. Compare the byte sequence against the official Minecraft protocol specification
4. Check [`pumpkin-protocol/src/serial/deserializer.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-protocol/src/serial/deserializer.rs) for 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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-world/src/world.rs). Verify that `ChunkPos` calculations in [`pumpkin/src/world/portal/mod.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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:

1. Check the scheduler logs in `pumpkin_plugin_api::scheduler` for task execution traces
2. Verify the plugin's `on_tick` implementation uses `tokio::spawn` for long-running work to avoid blocking the main tick thread
3. Ensure the plugin uses the API logger defined in [`pumpkin-plugin-api/src/logging.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-plugin-api/src/logging.rs) rather 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:

```bash
RUST_LOG=pumpkin_protocol=debug,pumpkin_world=debug cargo run --release

```

Next, add a targeted debug statement in [`pumpkin/src/player/mod.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin/src/player/mod.rs) to inspect the login packet fields:

```rust
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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-protocol/src/packet.rs).

## Summary

- **Structure first**: Map your bug to the correct crate—`pumpkin-protocol` for network issues, `pumpkin-world` for chunk errors, or `pumpkin-plugin-api` for extension crashes.
- **Log strategically**: Use `RUST_LOG=pumpkin_protocol=debug` to isolate specific modules without console spam.
- **Handle async complexity**: Attach LLDB to the Tokio runtime and enable `RUST_BACKTRACE=full` to trace panics across task boundaries.
- **Verify generated code**: Use `cargo expand` on `pumpkin-codegen` when packet structs behave unexpectedly.
- **Inspect serialization**: Check [`pumpkin-protocol/src/serial/serializer.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/pumpkin-protocol/src/serial/serializer.rs) and [`deserializer.rs`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/deserializer.rs) for 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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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`](https://github.com/Pumpkin-MC/Pumpkin/blob/main/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.