skills/debugging/runtime-error-explainer/SKILL.md
Translates cryptic runtime error messages and stack traces into understandable explanations, pointing to the concrete line at fault and the most likely fix. Use when a user pastes an error they don't understand, when a stack trace is deep and the user doesn't know where to start, or when an error message misleads about the real cause.
npx skillsauth add santosomar/general-secure-coding-agent-skills runtime-error-explainerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Turn a stack trace into a one-line answer: what broke, where, and why.
| Language / Runtime | Read direction | Your code is usually |
| ------------------ | ------------------------------------- | ---------------------------------------- |
| Python | Bottom-up (most recent call last) | Near the bottom, above the library frame |
| Java / Kotlin | Top-down (most recent call first) | Near the top, below the exception line |
| JavaScript / Node | Top-down | First non-node_modules frame |
| Go (panic) | Top-down, per goroutine | First frame in the panicking goroutine |
| Rust | Top-down (with RUST_BACKTRACE=1) | First non-std/core frame |
| C/C++ (gdb bt) | Top-down, #0 is crash site | First frame with source you own |
Rule: Find the first stack frame in code the user controls. That's where they look first, regardless of what the error message says.
The message points at line X. The bug is somewhere else. Catalog:
| Error | Where it points | Where the bug actually is |
| ---------------------------------------- | ---------------------------- | ----------------------------------------------------- |
| NullPointerException / NoneType has no attribute | The dereference | The earlier line that was supposed to assign the value |
| KeyError / undefined is not a function | The lookup | The code that built the dict/object and omitted the key |
| UnboundLocalError (Python) | The read of the variable | Any line in the function that assigns to it — Python decided it's local |
| SyntaxError: unexpected EOF | Last line of the file | An unclosed bracket/quote somewhere above — bisect by deleting halves |
| StackOverflowError / RecursionError | Deep in the recursion | The base case (missing or wrong), not the recursive call |
| SIGSEGV at 0x0 | The crash site | Whatever returned NULL and wasn't checked — walk up the stack |
| ConcurrentModificationException | The iterator's .next() | Whatever mutated the collection during iteration — different line, maybe different thread |
| CORS error (browser console) | The frontend fetch | The backend — missing Access-Control-Allow-Origin header |
| ECONNREFUSED | The client connect call | The server isn't running / wrong port / firewall — not a code bug at all |
Caused by: (Java), The above exception was the direct cause of (Python), InnerException (.NET). The innermost cause is the real error. Everything above it is packaging.
Unwrap until you hit the bottom. Explain that.
<var> is null at <file>:<line>. It was supposed to be set by <earlier-line>, which <didn't run | returned null | ran with wrong args>."<key> isn't in <object> at <file>:<line>. <object> was built at <earlier-line> — <key is conditional and the condition was false | key name is misspelled | the shape changed upstream>."<fn> at <file>:<line> expected <type> but got <actual>. <actual> came from <source> — <the API changed | a transform is missing | wrong variable passed>."<service> at <host>:<port> is <not running | unreachable | slow>. Verify: <concrete check command>."Input:
Traceback (most recent call last):
File "/app/api/handlers.py", line 89, in get_order
return serialize(order, user.preferences.currency)
File "/app/models/user.py", line 34, in __getattr__
return self._data[name]
KeyError: 'preferences'
Analysis: Python → bottom-up → error is KeyError: 'preferences'. First user-controlled frame is handlers.py:89, which accesses user.preferences. The __getattr__ frame is a dynamic attribute proxy — it reports what was missing but not why.
Explanation:
userhas nopreferencesattribute athandlers.py:89.
userhere comes from whatever loaded it — likely aUser.load()call earlier inget_order. Thepreferencesfield was never populated. Three common reasons: (a) the user row in the DB has no preferences set and the model doesn't default it; (b) the ORM query is doing a partialSELECTthat skips the column; (c)preferenceswas recently renamed/moved.First check:
print(user._data.keys())right before line 89.
exit 137 → OOM-killed; exit 139 → SIGSEGV. Look at system logs, not the app.await. Look for "task was created at" / asyncio origin tracking.NullPointerException is. Explain why this one happened.try/except as a fix. That's a symptom suppressor.## What broke
<one sentence — the real error, unwrapped>
## Where to look
<file>:<line> — <why this frame, not the one the error points at>
## Likely cause
<ranked list, 1–3 items, most likely first>
## Verify with
<one concrete diagnostic step — a print, a breakpoint, a query>
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.