Back to Skills

tokio-troubleshooting

verified

Debugging and troubleshooting Tokio applications using tokio-console, detecting deadlocks, memory leaks, and performance issues. Use when diagnosing async runtime problems.

View on GitHub

Marketplace

geoffjay-claude-plugins

geoffjay/claude-plugins

Plugin

rust-tokio-expert

languages

Repository

geoffjay/claude-plugins
7stars

plugins/rust-tokio-expert/skills/tokio-troubleshooting/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/geoffjay/claude-plugins/blob/main/plugins/rust-tokio-expert/skills/tokio-troubleshooting/SKILL.md -a claude-code --skill tokio-troubleshooting

Installation paths:

Claude
.claude/skills/tokio-troubleshooting/
Powered by add-skill CLI

Instructions

# Tokio Troubleshooting

This skill provides techniques for debugging and troubleshooting async applications built with Tokio.

## Using tokio-console for Runtime Inspection

Monitor async runtime in real-time:

```rust
// In Cargo.toml
[dependencies]
console-subscriber = "0.2"

// In main.rs
fn main() {
    console_subscriber::init();

    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            run_application().await
        });
}
```

**Run console in separate terminal:**
```bash
tokio-console
```

**Key metrics to monitor:**
- Task spawn rate and total tasks
- Poll duration per task
- Idle vs. busy time
- Waker operations
- Resource utilization

**Identifying issues:**
- Long poll durations: CPU-intensive work in async context
- Many wakers: Potential contention or inefficient polling
- Growing task count: Task leak or unbounded spawning
- High idle time: Not enough work or blocking operations

## Debugging Deadlocks and Hangs

Detect and resolve deadlock situations:

### Common Deadlock Pattern

```rust
// BAD: Potential deadlock
async fn deadlock_example() {
    let mutex1 = Arc::new(Mutex::new(()));
    let mutex2 = Arc::new(Mutex::new(()));

    let m1 = mutex1.clone();
    let m2 = mutex2.clone();
    tokio::spawn(async move {
        let _g1 = m1.lock().await;
        tokio::time::sleep(Duration::from_millis(10)).await;
        let _g2 = m2.lock().await; // May deadlock
    });

    let _g2 = mutex2.lock().await;
    tokio::time::sleep(Duration::from_millis(10)).await;
    let _g1 = mutex1.lock().await; // May deadlock
}

// GOOD: Consistent lock ordering
async fn no_deadlock_example() {
    let mutex1 = Arc::new(Mutex::new(()));
    let mutex2 = Arc::new(Mutex::new(()));

    // Always acquire locks in same order
    let _g1 = mutex1.lock().await;
    let _g2 = mutex2.lock().await;
}

// BETTER: Avoid nested locks
async fn best_example() {
    // Use message passing instead

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
10000 chars