Fix Bug
Guide for debugging and fixing bugs in Syncpack.
Scientific Debugging Workflow
- Observe — Understand the symptom precisely
- Hypothesise — Form a theory about the root cause
- Experiment — Test the hypothesis with targeted changes
- Validate — Confirm the fix with tests
- Verify — Run full test suite
Step 1: Observe
Gather information before changing code:
# Run the failing test with output
cargo test test_name -- --nocapture
# Run with backtrace
RUST_BACKTRACE=1 cargo test test_name
# Test against fixture
cd fixtures/fluid-framework
cargo run -- lint
Questions to answer:
- What is the exact error message?
- What input triggers it?
- What is the expected vs actual behaviour?
Step 2: Hypothesise
Common root causes by symptom:
| Symptom | Likely Cause |
|---|---|
State is Unknown | visit_packages not called or instance skipped |
| Wrong state assigned | Validation logic order, earlier check overriding |
| Instance not found | Package/dependency name mismatch, location format |
| Command not running | Missing registration in cli.rs, main.rs, or commands.rs |
| Panic/unwrap failure | Unexpected None or Err value |
Step 3: Experiment
Add targeted debug output:
use log::debug;
debug!("Instance: {:#?}", instance);
debug!("State before: {:?}", instance.state.borrow());
Search for related code:
# Find where state is assigned
ast-grep -p 'InstanceState::fixable' src/visit_packages/
# Find similar patterns
ast-grep -p 'PATTERN' src/
Step 4: Validate
Write a failing test FIRST (TDD):
#[test]
fn reproduces_the_bug() {
let ctx = TestBuilder::new()
.with_packages(vec![/* minimal reproduction */])
.build_and_visit_packages();
// Assert expected behaviour (will fail initially)
}
Then fix the code until the test passes.
Step 5: Verify
just test # All tests pass
cargo clippy # No warnings
Where to Look
By component
| Issue with... | Check... |
|---|---|
| CLI parsing | src/cli.rs |
| Config loading | src/config.rs, src/rcfile.rs |
| Package reading | src/packages.rs, src/package_json.rs |
| State assignment | src/visit_packages/*.rs |
| Command output | src/commands/*.rs, src/commands/ui/ |
| Version parsing | src/specifier/*.rs |
By phase
| Phase | What happens | Files |
|---|---|---|
| Create | Read config, packages, collect instances | context.rs, packages.rs |
| Inspect | Assign InstanceState | visit_packages.rs, visit_packages/*.rs |
| Run | Process instances, output/write | commands/*.rs |
Common Fixes
Instance state not being assigned
Check:
- Is the instance's version group variant handled in
visit_packages.rs? - Is there an early return skipping this instance?
- Is another validation assigning a state first?
Test assertion failing
Check:
- Is
build_and_visit_packages()called (not justbuild())? - Is the location string format correct? (
"{dep} in {location} of {package}") - Are there multiple instances of the same dependency?
Command not found
Verify registration in all three places:
src/cli.rs—Subcommandenumsrc/main.rs— match armsrc/commands.rs— module declaration
Debugging Tips
- Isolate — Create minimal reproduction
- Binary search — Comment out code to narrow down
- Print early — Add debug output before suspected area
- Check order — Validation order matters (first match wins)
- Read tests — Existing tests show expected behaviour
Anti-Patterns
❌ Changing code without understanding the cause ❌ Removing code just to make tests pass ❌ Fixing symptoms instead of root cause ❌ Skipping the test-first step