Debugging

Debug issues in Haskell and Python code. Use when something isn’t working, you see an error, or need to trace a problem.

Required Companion Skills

Before debugging, also load:

Process

  1. Reproduce - Can you trigger the error consistently?
  2. Isolate - What’s the minimal case that fails?
  3. Trace - Follow the error from symptom to cause
  4. Fix - Make the smallest change that fixes it
  5. Verify - Confirm the fix works and didn’t break anything

Reading Error Messages

Haskell

Foo.hs:42:15: error:
    • Couldn't match type 'Text' with 'String'
    • Expected: String
      Actual: Text

Common Haskell errors:

Python

Traceback (most recent call last):
  File "foo.py", line 42, in bar
    result = process(data)
  File "foo.py", line 10, in process
    return data["key"]
KeyError: 'key'

Common Python errors:

Checking Logs

Systemd services

journalctl -u <service-name> -f              # Follow logs
journalctl -u <service-name> --since "1 hour ago"
journalctl -u <service-name> -p err          # Errors only

Agent/subagent logs

ls ~/logs/subagents/                         # Subagent traces
cat ~/logs/orchestrator/*.log                # Orchestrator logs

Build logs

bild Omni/Thing.hs 2>&1 | less              # Capture and page

Common Issues

“Connection refused”

  1. Is the service running? systemctl status <service>
  2. Is it the right port? Check config
  3. Is it bound to localhost vs 0.0.0.0?
  4. Firewall? sudo iptables -L

“Permission denied”

  1. Check file permissions: ls -la <file>
  2. Check ownership: stat <file>
  3. Check if path is in protected directory
  4. Check systemd hardening (ProtectSystem, ReadOnlyPaths)

“Module not found”

  1. Check import statement matches file path
  2. Check the dep comment is present
  3. Run bild to regenerate

Infinite loop / hang

  1. Add print/trace statements to narrow down
  2. Check for recursive calls without base case
  3. Check for blocking I/O without timeout
  4. Use timeout command: timeout 10s command

Debugging Techniques

Print debugging

Haskell:

import Debug.Trace (trace, traceShow)

foo x = trace ("x = " <> show x) $ doThing x

Python:

print(f"DEBUG: x = {x}")

Simplify

Remove code until it works, then add back piece by piece.

Check assumptions

# Verify file exists
ls -la /path/to/file

# Verify command output
echo "input" | command

# Verify environment
env | grep RELEVANT_VAR

Search codebase

grep -r "error message" .
grep -r "function_name" --include="*.hs"

When Stuck

  1. Re-read the error message carefully
  2. Check if you’ve seen this before (search git history)
  3. Simplify to minimal reproduction
  4. Check documentation
  5. Ask for help - describe what you tried