stack-trace-decoder
4
总安装量
4
周安装量
#53743
全站排名
安装命令
npx skills add https://github.com/latestaiagents/agent-skills --skill stack-trace-decoder
Agent 安装分布
gemini-cli
4
opencode
4
antigravity
4
command-code
4
openhands
4
Skill 文档
Stack Trace Decoder
Parse, understand, and extract actionable insights from stack traces.
When to Use
- Understanding where an error originated
- Decoding minified/obfuscated traces
- Identifying the call chain leading to failure
- Comparing stack traces across incidents
- Explaining traces to team members
Stack Trace Anatomy
JavaScript/Node.js
Error: Cannot read properties of undefined (reading 'map')
at processItems (/app/src/services/processor.js:45:12)
at async handleRequest (/app/src/handlers/api.js:23:5)
at async Router.handle (/app/node_modules/express/router.js:156:3)
at async Layer.handle_request (/app/node_modules/express/layer.js:95:5)
Components:
Error: [Error Type]: [Error Message]
at [Function Name] ([File Path]:[Line]:[Column])
â â â â â
â â â â ââ Column number
â â â ââ Line number
â â ââ File path
â ââ Function where error occurred
ââ "at" indicates stack frame
Python
Traceback (most recent call last):
File "/app/main.py", line 45, in process_data
result = transform(data['items'])
File "/app/utils.py", line 23, in transform
return [item.upper() for item in items]
TypeError: 'NoneType' object is not iterable
Note: Python traces read bottom-to-top (error at bottom).
Java
java.lang.NullPointerException: Cannot invoke method on null object
at com.example.service.UserService.getProfile(UserService.java:89)
at com.example.controller.UserController.showProfile(UserController.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:897)
Caused by: java.sql.SQLException: Connection refused
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2181)
... 15 more
Note: Java traces can have “Caused by” chains showing root cause.
Decoding Strategy
Step 1: Find the Entry Point
The first frame (or last in Python) in YOUR code is usually most important.
function findRelevantFrame(trace: string, appPaths: string[]): Frame | null {
const frames = parseStackTrace(trace);
// Skip framework/library frames
for (const frame of frames) {
if (appPaths.some(p => frame.file.includes(p))) {
return frame;
}
}
return frames[0]; // Fallback to first frame
}
// Example: Find first frame in 'src/' directory
const relevantFrame = findRelevantFrame(trace, ['src/', 'app/']);
Step 2: Parse the Trace
interface StackFrame {
functionName: string;
file: string;
line: number;
column?: number;
isNative: boolean;
isAsync: boolean;
}
function parseJavaScriptTrace(trace: string): StackFrame[] {
const lines = trace.split('\n');
const frames: StackFrame[] = [];
for (const line of lines) {
// Match: "at functionName (file:line:col)"
const match = line.match(/at\s+(?:(async)\s+)?(\S+)\s+\((.+):(\d+):(\d+)\)/);
if (match) {
frames.push({
isAsync: match[1] === 'async',
functionName: match[2],
file: match[3],
line: parseInt(match[4]),
column: parseInt(match[5]),
isNative: match[3].includes('native') || match[3].includes('node:')
});
}
}
return frames;
}
Step 3: Identify the Error Type
const ERROR_PATTERNS = {
// JavaScript
'TypeError.*undefined': {
cause: 'Accessing property on undefined value',
fix: 'Add null check or optional chaining'
},
'TypeError.*not a function': {
cause: 'Calling something that is not a function',
fix: 'Check if the method exists and is spelled correctly'
},
'RangeError': {
cause: 'Value out of allowed range (array size, recursion)',
fix: 'Check for infinite recursion or large data'
},
'SyntaxError': {
cause: 'Invalid JavaScript syntax',
fix: 'Check for JSON parse errors or eval issues'
},
// Python
'KeyError': {
cause: 'Dictionary key does not exist',
fix: 'Use .get() with default or check key existence'
},
'AttributeError.*NoneType': {
cause: 'Calling method on None value',
fix: 'Add None check before method call'
},
// Java
'NullPointerException': {
cause: 'Calling method on null reference',
fix: 'Add null check or use Optional'
},
'ClassCastException': {
cause: 'Invalid type cast',
fix: 'Check object type before casting'
}
};
function identifyErrorPattern(trace: string): ErrorInfo | null {
for (const [pattern, info] of Object.entries(ERROR_PATTERNS)) {
if (new RegExp(pattern, 'i').test(trace)) {
return info;
}
}
return null;
}
Common Patterns
The Null Chain
// Error: Cannot read properties of undefined (reading 'email')
const email = user.profile.contact.email;
// â â â
// Any of these could be undefined
Solution:
const email = user?.profile?.contact?.email;
// Or
const email = user && user.profile && user.profile.contact?.email;
The Async Trace Gap
Error: Something went wrong
at processData (app.js:10) // Where error was thrown
// Gap - async boundary
at async Promise.all // No intermediate frames
Solution: Use Error.captureStackTrace or async stack traces:
// Enable in Node.js
Error.stackTraceLimit = 50;
// Or use --async-stack-traces flag
The Minified Trace
Error: t is not a function
at e.render (main.a3f2b1c.js:1:45678)
at t.update (main.a3f2b1c.js:1:23456)
Solution: Use source maps:
# Decode with source-map-cli
source-map resolve main.a3f2b1c.js.map 1 45678
The Caused-By Chain (Java)
ServiceException: Failed to process user
at UserService.process(UserService.java:50)
Caused by: DatabaseException: Query failed
at Database.query(Database.java:120)
Caused by: SQLException: Connection refused
at Driver.connect(Driver.java:80)
Reading: Start from the innermost “Caused by” – that’s the root cause.
Source Map Decoding
import { SourceMapConsumer } from 'source-map';
async function decodeMinifiedTrace(
trace: string,
sourceMap: string
): Promise<string> {
const consumer = await new SourceMapConsumer(JSON.parse(sourceMap));
const frames = parseJavaScriptTrace(trace);
const decoded = frames.map(frame => {
if (frame.file.includes('.min.') || frame.file.includes('.bundle.')) {
const original = consumer.originalPositionFor({
line: frame.line,
column: frame.column || 0
});
return {
...frame,
file: original.source || frame.file,
line: original.line || frame.line,
column: original.column || frame.column,
functionName: original.name || frame.functionName
};
}
return frame;
});
consumer.destroy();
return formatFrames(decoded);
}
AI-Assisted Decoding
Decode and explain this stack trace:
[paste stack trace]
Provide:
1. **Error Summary** - What went wrong in plain English
2. **Root Cause Location** - The file and line to look at
3. **Call Chain** - How the code got there
4. **Likely Cause** - What probably triggered this
5. **Suggested Fix** - How to resolve it
Also note if:
- This looks like a common pattern
- The error is in our code vs library code
- Additional context would help
Trace Comparison
function compareTraces(trace1: string, trace2: string): TraceComparison {
const frames1 = parseStackTrace(trace1);
const frames2 = parseStackTrace(trace2);
// Find common frames
const common = frames1.filter(f1 =>
frames2.some(f2 => f1.file === f2.file && f1.line === f2.line)
);
// Find divergence point
let divergeIndex = 0;
for (let i = 0; i < Math.min(frames1.length, frames2.length); i++) {
if (frames1[i].file !== frames2[i].file || frames1[i].line !== frames2[i].line) {
divergeIndex = i;
break;
}
}
return {
areSameError: common.length > frames1.length * 0.8,
commonFrames: common,
divergencePoint: divergeIndex,
uniqueToFirst: frames1.filter(f => !common.includes(f)),
uniqueToSecond: frames2.filter(f => !common.includes(f))
};
}
Best Practices
- Read from your code first – Skip framework frames initially
- Check the error message – Often tells you exactly what’s wrong
- Look for “Caused by” – The real error is often nested
- Enable source maps – Minified traces are useless
- Increase stack limit – Default 10 frames may not be enough
- Check async boundaries – Errors can lose context
- Compare with working state – What changed?