explain-js-error
v1.0.0
Published
A professional-grade JavaScript/Node.js error explainer with rich context, actionable fixes, stack trace analysis, and optional AI-powered explanations. Built for developers and teams.
Maintainers
Readme
explain-js-error
Professional-grade JavaScript & Node.js error explainer — pattern-matched explanations, actionable fix suggestions, full stack trace analysis, multiple output formats, and optional AI-powered deep diagnosis.
Why
Every developer has stared at TypeError: Cannot read properties of undefined (reading 'x') and wondered exactly why it happened and what to do next. explain-js-error gives you:
- 🔍 40+ error patterns across TypeError, ReferenceError, SyntaxError, RangeError, Node.js system errors, async/Promise errors, and ESM/CJS module errors
- 🧠 Stack trace analysis — parses your call stack, identifies the first frame in your code, filters out Node.js internals
- 💡 Actionable fix steps with numbered instructions and code examples
- 🎨 4 output formats — rich terminal, JSON, Markdown, and minimal plain text
- 🤖 Optional AI layer — pass the full stack to OpenAI GPT or Anthropic Claude for context-specific explanations
- ⚡ CLI with pipe support — pipe your
stderrdirectly and get instant explanations - 📦 Programmatic API — sync and async interfaces for use in any Node.js project
Installation
npm install explain-js-errorFor global CLI use:
npm install -g explain-js-errorCLI Usage
# Explain an error by message string
explain-error "Cannot read properties of undefined (reading 'name')"
# Explain an error with full stack trace from stdin (pipe)
node myScript.js 2>&1 | explain-error --stack
# Read from a log file
explain-error --file crash.log
# Different output formats
explain-error "ENOENT: no such file or directory" --format markdown
explain-error "Maximum call stack size exceeded" --format json
explain-error "myVar is not defined" --format minimal
# AI-powered explanation (requires API key)
OPENAI_API_KEY=sk-... explain-error "Cannot read properties of null" --ai
# Compact mode (fewer sections)
explain-error "is not a function" --compact
# Full option list
explain-error --helpCLI Options
| Flag | Description |
|------|-------------|
| --format <name> | Output format: terminal (default), json, markdown, minimal |
| --stack / -s | Read full stack trace from stdin |
| --file <path> | Read error from a log file |
| --ai | Enable AI-powered explanation |
| --provider <name> | Force AI provider: openai | anthropic |
| --model <name> | Override AI model |
| --no-example | Hide the code example section |
| --no-stack | Hide the call stack section |
| --compact / -c | Compact output |
| --no-color | Disable colors |
| --version | Show version |
| --help | Show help |
Programmatic API
Synchronous (no AI)
const explainError = require('explain-js-error');
// Catch real errors in try/catch
try {
const user = undefined;
console.log(user.name);
} catch (err) {
// Terminal output (colored, rich)
console.log(explainError(err));
// JSON output (for logging/integrations)
console.log(explainError(err, { format: 'json' }));
// Markdown output (for issue trackers)
console.log(explainError(err, { format: 'markdown' }));
}Async (with optional AI enrichment)
const { explainAsync } = require('explain-js-error');
try {
await riskyOperation();
} catch (err) {
// Auto-detects OPENAI_API_KEY / ANTHROPIC_API_KEY
const explanation = await explainAsync(err, { ai: true });
console.log(explanation);
}Raw Analysis (structured data)
const { analyze } = require('explain-js-error');
const result = analyze(new TypeError("Cannot read properties of undefined (reading 'map')"));
console.log(result.pattern.id); // 'cannot-read-undefined'
console.log(result.pattern.severity); // 'critical'
console.log(result.confidence); // 0.72 (0-1 scale)
console.log(result.stack.firstUserFrame.filePath); // '/your/file.js'
console.log(result.stack.firstUserFrame.line); // 42
console.log(result.pattern.fix); // ['Check if the variable is...', ...]Named exports
const {
explain, // sync explain — same as default export
explainAsync, // async explain with optional AI
analyze, // raw AnalysisResult — no formatting
formatResult, // format an AnalysisResult yourself
} = require('explain-js-error');AI-Powered Mode
Set your API key and the package automatically uses it:
# OpenAI (recommended for accuracy)
export OPENAI_API_KEY=sk-...
# Anthropic Claude (faster, cheaper)
export ANTHROPIC_API_KEY=sk-ant-...Then install the optional SDK:
npm install openai # for OpenAI
npm install @anthropic-ai/sdk # for AnthropicNow every call uses AI for context-specific explanations:
node app.js 2>&1 | explain-error --stack --aiThe AI receives the full error message, stack trace, and local pattern analysis, then provides a response that says exactly why this specific instance of the error occurred in your code.
Environment Variables
| Variable | Description |
|----------|-------------|
| OPENAI_API_KEY | Enables OpenAI GPT explanation |
| ANTHROPIC_API_KEY | Enables Anthropic Claude explanation |
| EXPLAIN_AI_MODEL | Override the AI model (e.g. gpt-4o, claude-3-5-sonnet-20241022) |
| NO_COLOR | Disable color output |
| DEBUG_EXPLAIN | Enable internal debug logging |
Supported Error Patterns
TypeError (15 patterns)
- Property access on
undefinedornull - Calling non-function values
- Using
newon non-constructors - Setting properties on
undefined/null - Reassigning
const - Iterating over
undefined/null reduce()on empty array with no initial value- Destructuring from
undefined/null - Symbol type coercion
- Object not extensible
- BigInt mixing
- Invalid array length
ReferenceError (4 patterns)
- Variable not defined (scope, typos, missing imports)
- Temporal Dead Zone (let/const before initialization)
- Undeclared variable in strict mode
- Invalid left-hand side assignment
SyntaxError (6 patterns)
- Unexpected token
- Unexpected end of input
- Duplicate variable declaration
- Invalid/illegal character (curly quotes, unicode)
importin non-module context (ERR_REQUIRE_ESM)- Function declaration in block (strict mode)
RangeError (4 patterns)
- Maximum call stack size exceeded (stack overflow)
- Invalid string length
- Invalid repeat count
- Number formatting out of range
Node.js System Errors (10 patterns)
ENOENT— file not foundEACCES— permission deniedEADDRINUSE— port in useMODULE_NOT_FOUND— missing npm packageERR_REQUIRE_ESM— require() of ESM moduleECONNRESET— connection resetECONNREFUSED— connection refusedEPERM— operation not permittedETIMEDOUT— connection timeoutENOMEM— out of memory
Async/Promise Errors (5 patterns)
- Unhandled Promise Rejection
Promise.all()failure- Missing
await(Promise pending) - Callback error not handled
- Unhandled
'error'event on EventEmitter
Module System Errors (3 patterns)
- Named export not found
- Circular dependency
- Relative module path not found
Integration Examples
Express.js global error handler
const explainError = require('explain-js-error');
app.use((err, req, res, next) => {
const { analyze } = explainError;
const result = analyze(err);
// Log rich explanation to console
console.error(explainError(err, { format: 'minimal' }));
// Return structured JSON to client (dev mode only)
if (process.env.NODE_ENV === 'development') {
res.status(500).json(JSON.parse(explainError(err, { format: 'json' })));
} else {
res.status(500).json({ error: 'Internal server error' });
}
});Jest / test framework integration
// In jest.setup.js
const explainError = require('explain-js-error');
process.on('uncaughtException', (err) => {
console.error(explainError(err));
});CI pipeline (GitHub Actions)
- name: Run tests
run: |
node test/run.js 2>&1 | npx explain-error --stack --format minimal
continue-on-error: trueOutput Formats
Terminal (default)
Rich colored output with:
- Error type, message, pattern ID, and confidence score
- Origin — function name, file, and line number
- Full explanation with text wrapping
- Numbered fix steps
- Code example with broken/fixed comparison
- Filtered call stack (your code only)
- Docs link
JSON
{
"version": "1.0",
"timestamp": "2025-01-01T00:00:00.000Z",
"error": { "type": "TypeError", "message": "..." },
"analysis": {
"patternId": "cannot-read-undefined",
"title": "Accessing property on undefined",
"severity": "critical",
"confidence": 75,
"confidenceLabel": "high"
},
"explanation": "...",
"fix": ["...", "..."],
"stackTrace": {
"firstUserFrame": { "functionName": "...", "filePath": "...", "line": 42 }
}
}Markdown
GitHub-compatible Markdown suitable for:
- Issue tracker bug reports
- Log file outputs
- Slack/Teams messages (with markdown support)
Minimal
[ERROR] TypeError: Cannot read properties of undefined (reading 'name')
[PATTERN] cannot-read-undefined | Severity: critical | Confidence: 75%
[TITLE] Accessing property on undefined
[EXPLANATION] You are trying to access a property...
[FIX 1] Check if the variable is declared...
[ORIGIN] getUserName at /app/src/user.js:42
[DOCS] https://developer.mozilla.org/...Development
git clone https://github.com/your-username/explain-js-error
cd explain-js-error
npm install
npm testProject Structure
explain-js-error/
├── bin/cli.js # CLI entrypoint
├── src/
│ ├── index.js # Public API
│ ├── analyzer.js # Core multi-pass scoring engine
│ ├── stackParser.js # V8 stack trace parser
│ ├── patterns/ # Error pattern database
│ │ ├── typeErrors.js
│ │ ├── referenceErrors.js
│ │ ├── syntaxErrors.js
│ │ ├── rangeErrors.js
│ │ ├── nodeErrors.js
│ │ ├── asyncErrors.js
│ │ ├── moduleErrors.js
│ │ └── index.js
│ ├── formatter/ # Output formatters
│ │ ├── terminal.js
│ │ ├── json.js
│ │ ├── markdown.js
│ │ ├── minimal.js
│ │ └── index.js
│ └── ai/ # Optional AI adapters
│ ├── openai.js
│ ├── anthropic.js
│ └── index.js
└── test/
├── analyzer.test.js
├── stackParser.test.js
├── formatter.test.js
└── run-tests.jsLicense
MIT © explain-js-error contributors
