Debugging Hanging Tests
SkillDev toolsDiagnosing and fixing hanging worker executor or integration tests. Use when a test hangs indefinitely, times out, or appears stuck during execution.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Debugging Hanging Tests skill
What this skill tells your AI
The instructions your AI receives, as published by golemcloud/golem in .agents/skills/debugging-hanging-tests/SKILL.md and read by ahel’s review.
Worker executor and integration tests can hang indefinitely due to unimplemented!() panics in async tasks, deadlocks, missing shard assignments, or other async runtime issues. This skill provides a systematic workflow for diagnosing and resolving these hangs.
Common Causes
| Cause | Symptom |
|---|---|
unimplemented!() panic in async task | Test hangs after a log line mentioning the unimplemented feature |
| Deadlock | Test hangs with no further log output |
| Missing shard assignment | Worker never starts executing |
| Channel sender dropped | Receiver awaits forever with no error |
| Infinite retry loop | Repeated log lines with the same error |
Step 1: Add a Timeout
Add a #[timeout] attribute so the test fails with a clear error instead of hanging forever:
use test_r::test;
use test_r::timeout;
#[test]
#[timeout("30s")]
async fn my_hanging_test() {
// ...
}
Choose a timeout generous enough for normal execution but short enough to fail quickly when hung (30s–60s for most tests, up to 120s for complex integration tests).
Step 2: Capture Full Output
Run the test with --nocapture and save all output to a file. The root cause often appears far before the point where the test hangs:
cargo test -p <crate> <test_name> -- --nocapture > tmp/test_output.txt 2>&1
Important: Always redirect to a file. The output can be thousands of lines, and the relevant error may be near the beginning while the hang occurs at the end.
Step 3: Search for Root Cause
Search the saved output file for these patterns, in order of likelihood:
rg -n "unimplemented" tmp/test_output.txt
rg -n "panic" tmp/test_output.txt
rg -n "ERROR" tmp/test_output.txt
rg -n "WARN" tmp/test_output.txt
What to look for
not yet implementedorunimplemented: An async task hit an unimplemented code path and panicked. The panic is silently swallowed by the async runtime, causing the caller to await forever.panic: Similar to above — a panic in a spawned task won't propagate to the test.ERRORwith retry: A service call failing repeatedly, causing an infinite retry loop.- Repeated identical log lines: Indicates a retry loop or polling cycle that never succeeds.
Step 4: Fix the Root Cause
If caused by unimplemented!()
Implement the missing functionality, or if it's a test-only issue, provide a stub/mock.
If caused by a deadlock
Look for:
- Multiple
lock()calls on the same mutex in nested scopes awaitwhile holding a lock guard- Circular lock dependencies between tasks
If caused by missing shard assignment
Check that the test setup properly initializes the shard manager and assigns shards before starting workers.
If caused by a dropped sender
Ensure all channel senders are kept alive for the duration the receiver needs them. Check for early returns or error paths that drop the sender.
Checklist
#[timeout("30s")]added to the hanging test- Test run with
--nocapture, output saved to file - Output searched for
unimplemented,panic,ERROR - Root cause identified and fixed
- Test passes within the timeout
- Remove the
#[timeout]if it was only added for debugging (or keep it as a safety net)
Signals
- GitHub stars
- 2k
- Forks
- 212
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
debugging-hanging-tests- Source
- github.com/golemcloud/golem