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.
Install with Tessl CLI
npx tessl i github:santosomar/general-secure-coding-agent-skills --skill runtime-error-explainer100
Quality
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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>47d56bb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.