
Rspack Debugging
- 187 installs
- 86 repo stars
- Updated August 4, 2026
- rstackjs/agent-skills
Use rspack-debugging for development tasks
About
rspack-debugging: A skill for development. This provides functionality for development workflows.
- rspack-debugging
Rspack Debugging by the numbers
- 187 all-time installs (skills.sh)
- +4 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #2,132 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rstackjs/agent-skills --skill rspack-debuggingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 187 |
|---|---|
| repo stars | ★ 86 |
| Last updated | August 4, 2026 |
| Repository | rstackjs/agent-skills ↗ |
What it does
Use rspack-debugging for development tasks
Files
Rspack Debugging
Overview
This Skill guides you on how to capture the underlying crash state of Rspack (which is based on Rust). By using the LLDB debugger and Rspack packages with debug symbols, we can obtain detailed stack backtraces, which are crucial for pinpointing issues. The guides focus on non-interactive, automated debugging to easily capture backtraces.
Preparation
Before starting, please ensure your environment meets the requirements.
1. Install LLDB: You must install the LLDB debugger.
- macOS: Run
xcode-select --install - Linux: Install the
lldbpackage (e.g.,apt-get install lldb) - Detailed guide: references/lldb.md
2. Replace Debug Packages: Production packages like @rspack/core have debug symbols stripped. They must be replaced with the @rspack-debug/* series packages to see useful stack information.
Automatic Replacement Script:
node ${CLAUDE_PLUGIN_ROOT}/skills/debugging/scripts/setup_debug_deps.cjsRunning the above script will automatically add pnpm.overrides configuration to package.json, pointing Rspack packages to their corresponding Debug versions. Afterwards, please be sure to run pnpm install to update dependencies.
Debugging Workflows
Identify your specific scenario and follow the corresponding linked guide.
Detailed Guides
Detailed Guides
Guide A: Crash during HMR
Scenario: Stable Crash/Deadlock during DevServer HMR. Read Guide: references/guide_a_hmr_crash.md
Guide B: Crash during Build
Scenario: Stable Crash/Deadlock during Build (or Unstable Build Crash that is frequent enough). Read Guide: references/guide_b_build_crash.md
Guide C: Attach to Stuck Process
Scenario: Unstable Deadlock during Build (happens randomly). Read Guide: references/guide_c_attach_to_stuck_process.md
Guide D: Coredump Analysis (Dev)
Scenario: Unstable Crash during DevServer HMR (hard to catch interactively). Read Guide: references/guide_d_coredump_analysis_dev.md
Guide E: Coredump Analysis (Build)
Scenario: Unstable Crash during Build. Read Guide: references/guide_e_coredump_analysis_build.md
Guide F: Async Deadlock Identification
Scenario: Unstable Async Deadlock. Main thread stuck in uv_run. Read Guide: references/guide_f_async_deadlock.md
Saving Debug Artifacts
Critical Instruction for Agents: When you successfully obtain a backtrace or a tracing log, you MUST save it to a local file in the user's project directory so it is preserved after the session.
1. Create Directory: Ensure a directory named debug_artifacts exists in the project root. 2. Save Backtraces: Write the full output of thread backtrace all to debug_artifacts/backtrace_<timestamp>.txt. 3. Save Tracing Logs: (Only if using Tracing Skill)
Environment Restoration
After debugging is complete, restore your package.json to use production packages:
node ${CLAUDE_PLUGIN_ROOT}/skills/debugging/scripts/setup_debug_deps.cjs --restore
pnpm installGuide A: Crash during HMR
Scenario: Stable Crash/Deadlock during DevServer HMR.
1. Launch LLDB (Non-Interactive): Run the following command to start the dev server under LLDB. It will automatically run, and if it crashes, it will print the backtrace and exit.
# Adjust the path to rspack.js if needed
lldb --batch -o "run" -k "thread backtrace all" -k "quit" -- node node_modules/@rspack/cli/bin/rspack.js dev2. Trigger the Issue:
- Wait for the Dev Server to start.
- Modify a source file to trigger HMR.
3. Get Backtrace:
- If it Crashes: The backtrace will be printed to stdout automatically.
- If it Hangs (Deadlock): Press
Ctrl + Cin the running terminal. LLDB should catch the signal and might need manual intervention if not configured to catch SIGINT. - _Better approach for Hangs_: Use
Guide CorGuide F.
4. Save Output: Agent Action: Save the printed backtrace to debug_artifacts/backtrace_hmr_crash.txt.
Guide B: Crash during Build
Scenario: Stable Crash during Build.
1. Launch LLDB (Non-Interactive): Run the build command under LLDB in batch mode.
lldb --batch -o "run" -k "thread backtrace all" -k "quit" -- node node_modules/@rspack/cli/bin/rspack.js build2. Wait for Result:
- The command will run until it crashes or finishes.
- On crash, it prints the stack trace of all threads.
3. Save Output: Agent Action: Save the output to debug_artifacts/backtrace_build_crash.txt.
Guide C: Attach to Stuck Process
Scenario: Unstable Deadlock during Build (happens randomly).
1. User Action: Reproduce and Get PID
Run the following script to loop your build command until it hangs. This script prints the PID of each attempt.
# Loop until you manually stop it (Ctrl+C) when it hangs
while true; do
echo "Starting build..."
# Start in background to get PID easily, then wait
pnpm build &
PID=$!
echo ">> Process PID: $PID"
wait $PID
echo "Build finished, retrying..."
sleep 1
doneInstructions:
1. Run the script in your terminal. 2. Watch the output. 3. When the build hangs (stops outputting and doesn't finish for a long time):
- Look at the last printed
>> Process PID: <NUMBER>. - Do not kill the process.
- Copy that PID.
2. Agent Action: Attach and debug
Ask the user for the PID of the stuck process. Once obtained, run:
# Replace <PID> with the actual number provided by the user
lldb -p <PID> --batch -o "thread backtrace all" -o "quit"3. Save Output
Agent Action: Save the output to debug_artifacts/backtrace_attached.txt.
Guide D: Coredump Analysis (Dev)
Scenario: Unstable Crash during DevServer HMR (hard to catch interactively).
1. Enable Core Dumps: Run this in the terminal where you will start the dev server:
ulimit -c unlimited_Note: On macOS, core dumps might be written to /cores/. On Linux, usually current dir or /var/lib/systemd/coredump._ 2. Start Dev Server:
pnpm dev3. Torture Test: Repeatedly modify files to trigger HMR until the server crashes. You can write a script to append a comment to a file every second. 4. Locate Core File: Find the generated core file (e.g., /cores/core.12345 or ./core). 5. Debug Post-Mortem:
# You need the exact node binary that ran the process
lldb --batch -o "thread backtrace all" -o "quit" --core /path/to/core_file $(which node)6. Get Backtrace: The backtrace will be printed to stdout. 7. Save Output: Agent Action: Save the output from step 6 to debug_artifacts/backtrace_core_dump.txt.
Guide E: Coredump Analysis (Build)
Scenario: Unstable Crash during Build.
1. Enable Core Dumps:
ulimit -c unlimited2. Loop until Crash:
# Simple shell loop
while pnpm build; do echo "Build success, retrying..."; doneWait for the loop to exit with an error (Segmentation fault). 3. Debug Post-Mortem:
lldb --batch -o "thread backtrace all" -o "quit" --core /path/to/core_file $(which node)4. Get Backtrace: The backtrace will be printed to stdout. 5. Save Output: Agent Action: Save the output from step 4 to debug_artifacts/backtrace_core_dump.txt.
Guide F: Async Deadlock Identification
Scenario: Unstable Async Deadlock. Main thread stuck in uv_run.
1. Identification
Use Guide C (Attach to Stuck Process) to get a backtrace from the stuck process. Then check if it matches the following pattern:
Main Thread Stuck in the event loop waiting (uv_run / kevent / epoll_wait), usually with no active JavaScript or Rust tasks.
frame #0: kevent (libsystem_kernel.dylib)
frame #1: uv__io_poll (node)
frame #2: uv_run (node)
frame #3: node::SpinEventLoopInternal (node)Tokio Worker Threads All in an idle waiting state (Condvar::wait).
frame #0: __psynch_cvwait
frame #1: _pthread_cond_wait
frame #2: parking_lot::condvar::Condvar::wait_until_internal
frame #3: tokio::runtime::scheduler::multi_thread::park::Parker::park2. Next Steps
If the backtrace matches the above pattern, it is a classic Async Deadlock. LLDB cannot help further because the threads are simply waiting for a Future that never completes.
Recommendation: Please use the Tracing Skill to diagnose this issue. Tracing logs can reveal which Future was last active or dropped.
LLDB References
Install
LLDB is the debugger for the LLVM project. Since Rspack is written in Rust, LLDB can be used for debugging.
macOS
On macOS, LLDB usually comes installed with Xcode or Command Line Tools.
1. Check if it is already installed:
lldb --version2. If not installed, run the following command to install Command Line Tools:
xcode-select --installLinux
Ubuntu / Debian
sudo apt-get update
sudo apt-get install lldbArch Linux
sudo pacman -S lldbWindows
Windows users are recommended to use WSL2 (Ubuntu) and follow the Linux steps for installation, or use the C++ extension in VS Code with LLDB. If you are in a native Windows environment, you can use the Windows installer provided by the LLVM official website, but debugging Rspack is generally recommended in a Unix-like environment for better support.
LLDB in Batch Mode
For automation and non-interactive debugging, we use LLDB in batch mode:
lldb --batch -o "run" -k "thread backtrace all" -k "quit" -- node script.js--batch: Run in batch mode.-o: Execute command after loading.-k: Execute command upon crash (if the process crashes).--: Separate LLDB arguments from the target program arguments.
Common Checks
thread backtrace all (or bt all)
This is the most critical command. It prints the stack traces of all threads.
frame variable (or fr v)
Prints variables in the current stack frame. Can be used with -o to inspect specific states if needed.
const fs = require('fs');
const path = require('path');
const USER_MIN_VERSION = '1.3.14';
/**
* Recursively find a file upwards from the start directory.
*/
function findFileUpwards(startDir, fileName) {
let currentDir = startDir;
while (true) {
const filePath = path.join(currentDir, fileName);
if (fs.existsSync(filePath)) {
return filePath;
}
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
// Reached root
return null;
}
currentDir = parentDir;
}
}
// Find pnpm-lock.yaml to determine the workspace root
const lockPath = findFileUpwards(process.cwd(), 'pnpm-lock.yaml');
if (!lockPath) {
console.error('❌ No pnpm-lock.yaml found in current or parent directories.');
console.error(' This script requires a pnpm project with a lockfile.');
process.exit(1);
}
const workspaceRoot = path.dirname(lockPath);
const pkgPath = path.join(workspaceRoot, 'package.json');
const backupPath = path.join(workspaceRoot, 'package.json.bak');
console.log(`📍 Workspace Root detected: ${workspaceRoot}`);
function restore() {
if (fs.existsSync(backupPath)) {
fs.copyFileSync(backupPath, pkgPath);
console.log(`✅ Restored package.json from backup at ${backupPath}`);
fs.unlinkSync(backupPath);
} else {
console.log(`No backup found at ${backupPath} to restore.`);
}
}
if (process.argv.includes('--restore')) {
restore();
process.exit(0);
}
if (!fs.existsSync(pkgPath)) {
console.error(`❌ No package.json found at workspace root: ${pkgPath}`);
process.exit(1);
}
// Simple version comparison (major.minor.patch)
function isVersionLessThan(v1, v2) {
const parts1 = v1.split('.').map(Number);
const parts2 = v2.split('.').map(Number);
for (let i = 0; i < 3; i++) {
if (parts1[i] < parts2[i]) return true;
if (parts1[i] > parts2[i]) return false;
}
return false;
}
// Backup first
if (!fs.existsSync(backupPath)) {
fs.copyFileSync(pkgPath, backupPath);
console.log(`📦 Created backup of package.json at ${backupPath}`);
}
console.log('🔎 Searching for @rspack/core version in pnpm-lock.yaml...');
const lockContent = fs.readFileSync(lockPath, 'utf-8');
// Grep logic for pnpm-lock.yaml
// Matches /@rspack/core@1.0.0: or /@rspack/core@1.0.0(
const versionMatch = lockContent.match(/\@rspack\/core@([^\s:'()]+)/);
if (!versionMatch) {
console.error('❌ Could not find "@rspack/core" in pnpm-lock.yaml.');
process.exit(1);
}
let version = versionMatch[1];
console.log(`✅ Detected Rspack version: ${version}`);
if (isVersionLessThan(version, USER_MIN_VERSION)) {
console.warn(`\n⚠️ WARNING: @rspack-debug/* packages are only officially supported for versions >= ${USER_MIN_VERSION}.`);
console.warn(` Current version is ${version}. Falling back to debug version ${USER_MIN_VERSION}.`);
console.warn(` This may lead to binary incompatibility if there are major API changes.\n`);
version = USER_MIN_VERSION;
}
// Update package.json
const pkg = require(pkgPath);
pkg.pnpm = pkg.pnpm || {};
pkg.pnpm.overrides = pkg.pnpm.overrides || {};
const debugCore = `npm:@rspack-debug/core@${version}`;
const debugCli = `npm:@rspack-debug/cli@${version}`;
console.log(`🔄 Configuring pnpm overrides in workspace root package.json:`);
console.log(` @rspack/core -> ${debugCore}`);
console.log(` @rspack/cli -> ${debugCli}`);
pkg.pnpm.overrides['@rspack/core'] = debugCore;
pkg.pnpm.overrides['@rspack/cli'] = debugCli;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
console.log(`✅ package.json at ${workspaceRoot} updated.`);
console.log('\n👉 Next Step: Run `pnpm install` in the workspace root to apply the overrides.');
console.log(' To revert changes, run this script with --restore');