| name | error-messages |
| description | Write helpful, actionable error messages instead of vague ones. Use this skill when writing error handling code, throw/raise statements, logging errors, or reviewing error messages. Triggers on tasks involving try/catch blocks, error responses, validation errors, API error handling, or any code that produces user-facing or developer-facing error messages. |
| license | MIT |
| metadata | {"author":"leoisadev1","version":"1.0.0"} |
Error Messages That Actually Help
Stop writing error messages like "Something went wrong" or "Invalid input." Write error messages for the person who'll see them at 2am when everything is broken.
When to Apply
Use these guidelines when:
- Writing try/catch or error handling blocks
- Creating validation error messages
- Building API error responses
- Logging errors for debugging
- Writing user-facing error states
- Reviewing code that produces error messages
The Four Requirements
Every error message MUST include:
| Requirement | Description | Bad Example | Good Example |
|---|
| What happened | The specific thing that failed, not just "error" | "Error: Operation failed" | "Payment processing failed: card declined" |
| Why it happened | The condition that triggered the error | "Invalid request" | "Card has insufficient funds ($12.50 available, $50.00 requested)" |
| What to do about it | The action that would fix it or the next step | (nothing) | "Try a different payment method or contact the customer" |
| Relevant context | IDs, values, timestamps — anything that helps locate the problem | (nothing) | "Customer ID: cust_12345, Transaction ID: txn_67890" |
Rules
Rule 1: Never Write Vague Error Messages
Bad:
throw new Error("Invalid input")
throw new Error("Operation failed")
throw new Error("Something went wrong")
raise ValueError("Bad value")
return res.status(400).json({ error: "Bad request" })
Good:
throw new Error(
`Invalid email format: "${email}" is missing @ symbol. ` +
`Expected format: user@domain.com`
)
throw new Error(
`Failed to create user: username "${username}" already exists. ` +
`Try a different username or log in to the existing account.`
)
Rule 2: Include the Actual Values That Caused the Error
Bad:
if (age < 0) throw new Error("Invalid age")
if (!items.length) throw new Error("No items found")
Good:
if (age < 0) throw new Error(
`Invalid age: ${age}. Age must be a non-negative number.`
)
if (!items.length) throw new Error(
`No items found for query "${query}" in collection "${collection}". ` +
`Verify the collection name and query parameters.`
)
Rule 3: Include IDs and Timestamps for Debugging
Bad:
logger.error("Database connection failed")
logger.error("Request timeout")
Good:
logger.error(
`Database connection failed: ${err.message}. ` +
`Host: ${dbHost}, Port: ${dbPort}, Database: ${dbName}. ` +
`Retries exhausted (${maxRetries}/${maxRetries}). ` +
`Check database status and network connectivity.`
)
logger.error(
`Request timeout after ${timeoutMs}ms. ` +
`Endpoint: ${method} ${url}, Request ID: ${requestId}. ` +
`Consider increasing timeout or checking upstream service health.`
)
Rule 4: API Errors Should Be Machine-Readable AND Human-Readable
Bad:
{ "error": "Bad request" }
{ "error": "Not found" }
Good:
{
"error": {
"code": "INSUFFICIENT_FUNDS",
"message": "Payment failed: Card declined due to insufficient funds.",
"details": {
"customer_id": "cust_12345",
"amount_requested": 5000,
"currency": "usd"
},
"suggestion": "Try a different card or reduce the payment amount."
}
}
Rule 5: Validation Errors Should Name the Field and Expectation
Bad:
"Validation failed"
"Invalid field"
"Required field missing"
Good:
`Validation failed on field "email": value "${value}" does not match ` +
`expected format (user@domain.com). Received type: ${typeof value}.`
`Required field "shipping_address.zip_code" is missing. ` +
`All US shipping addresses require a 5 or 9 digit ZIP code.`
Rule 6: Rate Limit and Quota Errors Should Include Numbers
Bad:
"Rate limit exceeded"
"Too many requests"
Good:
`API rate limit exceeded: ${used}/${limit} requests used. ` +
`Resets in ${secondsUntilReset} seconds (${resetTime}). ` +
`Consider implementing exponential backoff or request batching.`
`Storage quota exceeded: ${usedMB}MB / ${limitMB}MB used. ` +
`Free up ${neededMB}MB to complete this upload. ` +
`Largest files: ${topFiles.join(", ")}.`
Rule 7: Permission Errors Should Say What's Needed
Bad:
"Access denied"
"Forbidden"
"Unauthorized"
Good:
`Access denied: User "${userId}" lacks permission "${requiredPermission}" ` +
`on resource "${resourceType}/${resourceId}". ` +
`Contact your admin to request the "${requiredRole}" role.`
`Authentication expired: Token issued at ${issuedAt} expired at ${expiredAt}. ` +
`Re-authenticate at ${authUrl} to get a new token.`
Quick Reference
When you write code that can fail, ask yourself: "If this fails at 2am, what would I want to know?"
Put that information in the error message:
- What failed (specific operation, not "error")
- Why it failed (the condition, constraint, or value that triggered it)
- How to fix it (next step, workaround, or who to contact)
- Context (IDs, values, timestamps, request details)
The extra 30 seconds writing a helpful error message saves hours of debugging later. Not just for you, but for everyone who'll ever see that error.