CtrlK
BlogDocsLog inGet started
Tessl Logo

runtime-error-explainer

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-explainer
What are skills?

100

Quality

100%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SKILL.md
Review
Evals

Runtime Error Explainer

Turn a stack trace into a one-line answer: what broke, where, and why.

Read the stack in the right order

Language / RuntimeRead directionYour code is usually
PythonBottom-up (most recent call last)Near the bottom, above the library frame
Java / KotlinTop-down (most recent call first)Near the top, below the exception line
JavaScript / NodeTop-downFirst non-node_modules frame
Go (panic)Top-down, per goroutineFirst frame in the panicking goroutine
RustTop-down (with RUST_BACKTRACE=1)First non-std/core frame
C/C++ (gdb bt)Top-down, #0 is crash siteFirst 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.

Errors that lie about where the problem is

The message points at line X. The bug is somewhere else. Catalog:

ErrorWhere it pointsWhere the bug actually is
NullPointerException / NoneType has no attributeThe dereferenceThe earlier line that was supposed to assign the value
KeyError / undefined is not a functionThe lookupThe code that built the dict/object and omitted the key
UnboundLocalError (Python)The read of the variableAny line in the function that assigns to it — Python decided it's local
SyntaxError: unexpected EOFLast line of the fileAn unclosed bracket/quote somewhere above — bisect by deleting halves
StackOverflowError / RecursionErrorDeep in the recursionThe base case (missing or wrong), not the recursive call
SIGSEGV at 0x0The crash siteWhatever returned NULL and wasn't checked — walk up the stack
ConcurrentModificationExceptionThe iterator's .next()Whatever mutated the collection during iteration — different line, maybe different thread
CORS error (browser console)The frontend fetchThe backend — missing Access-Control-Allow-Origin header
ECONNREFUSEDThe client connect callThe server isn't running / wrong port / firewall — not a code bug at all

Chained/wrapped exceptions

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.

Translation templates

  • NPE/AttributeError: "<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>."
  • KeyError/missing attribute: "<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>."
  • Type error: "<fn> at <file>:<line> expected <type> but got <actual>. <actual> came from <source><the API changed | a transform is missing | wrong variable passed>."
  • Timeout/Connection refused: "This isn't a code bug. <service> at <host>:<port> is <not running | unreachable | slow>. Verify: <concrete check command>."

Worked example

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:

user has no preferences attribute at handlers.py:89.

user here comes from whatever loaded it — likely a User.load() call earlier in get_order. The preferences field 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 partial SELECT that skips the column; (c) preferences was recently renamed/moved.

First check: print(user._data.keys()) right before line 89.

Edge cases

  • No stack trace, just an exit code: exit 137 → OOM-killed; exit 139 → SIGSEGV. Look at system logs, not the app.
  • Stack trace is all library frames: The user's code is the thing that called into the library. Find the boundary.
  • Async/event-loop traces: The stack is shallow and unhelpful because the real caller is on the other side of an await. Look for "task was created at" / asyncio origin tracking.
  • Minified JS / stripped binary: Stack frame names are garbage. Ask for source maps / debug symbols before continuing.

Do not

  • Do not paraphrase the error message. "You got a NullPointerException" is not an explanation.
  • Do not explain what a NullPointerException is. Explain why this one happened.
  • Do not suggest wrapping the line in try/except as a fix. That's a symptom suppressor.
  • Do not stop at the crash line when the table above says the bug is upstream.

Output format

## 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>
Repository
santosomar/general-secure-coding-agent-skills
Last updated
Created

Is this your skill?

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.