Write custom instructions for AI coding tools by defining your error response schema (success flag, nested error object with code/message/details, timestamp, requestId) and requiring the AI to implement exactly this structure in all generated error handling code. Custom instructions ensure consistent API error responses across generated code without requiring repeated schema specification in each prompt.
This guide shows you practical techniques for writing custom instructions that ensure AI-generated error handling code always follows your error response schema.
Understanding Error Response Schemas
Before writing custom instructions, you need a clearly defined error response schema. Most modern APIs use a standardized format like this:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid data",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
],
"timestamp": "2026-03-16T10:30:00Z",
"requestId": "req_abc123"
}
}
This schema includes a success flag, nested error object with code, message, details array, timestamp, and request ID. Your custom instructions must communicate this structure clearly.
Why AI Deviates From Your Schema Without Instructions
AI coding assistants learn from millions of codebases and naturally produce the patterns they have seen most frequently. GPT-4 and Claude have ingested thousands of Express.js, FastAPI, and Django projects, each with different error response conventions. Without explicit guidance, the model picks the structure that statistically fits the surrounding code—which may be RFC 7807 Problem Details, a flat { error: "message" } object, or any number of other patterns.
The result is drift: the first endpoint your AI generates returns { success, error: { code, message } }, the second returns { status: "error", message: "..." }, and the third returns { errors: [...] }. Consumers of your API now need branching logic to handle every variant. Custom instructions lock the AI into a single canonical structure before it writes a single line.
Writing Effective Custom Instructions
Specify the Exact Schema Structure
The most important rule is being explicit about your error response structure. Instead of saying “use proper error formatting,” specify every field:
When generating error responses, always use this exact structure:
{
"success": boolean,
"error": {
"code": string (uppercase with underscores, e.g., "VALIDATION_ERROR"),
"message": string (human-readable description),
"details": array of { field: string, message: string } (optional),
"timestamp": string (ISO 8601 format),
"requestId": string (prefixed with "req_")
}
}
This level of detail prevents AI from inventing fields or using different structures across endpoints.
Define Error Code Conventions
Your custom instructions should specify how error codes are formatted and what codes are available. Create a clear mapping:
Error codes must use UPPERCASE_WITH_UNDERSCORES format. Use these codes:
- VALIDATION_ERROR: Request validation failed
- AUTHENTICATION_ERROR: Invalid or missing authentication
- AUTHORIZATION_ERROR: Insufficient permissions
- NOT_FOUND: Resource does not exist
- RATE_LIMIT_ERROR: Too many requests
- INTERNAL_ERROR: Unexpected server error
- EXTERNAL_SERVICE_ERROR: Third-party service unavailable
With this guidance, AI generates consistent error codes instead of variations like “validation-error,” “invalid_input,” or “bad_request.”
Include Code Generation Examples
Concrete examples are more effective than abstract rules. Provide a complete example of error handling in your target language:
// For Express.js applications, use this pattern:
app.use((err, req, res, next) => {
if (err.name === 'ValidationError') {
return res.status(400).json({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: err.message,
details: err.details || undefined,
timestamp: new Date().toISOString(),
requestId: req.headers['x-request-id'] || `req_${crypto.randomUUID()}`
}
});
}
// Handle other error types similarly
});
Place this example in your custom instructions to show the AI exactly how error handling should look in your codebase.
Specify HTTP Status Code Mappings
Error response schemas often pair with specific HTTP status codes. Make these mappings explicit:
Map error codes to HTTP status codes:
- VALIDATION_ERROR -> 400
- AUTHENTICATION_ERROR -> 401
- AUTHORIZATION_ERROR -> 403
- NOT_FOUND -> 404
- RATE_LIMIT_ERROR -> 429
- INTERNAL_ERROR -> 500
- EXTERNAL_SERVICE_ERROR -> 502
This ensures AI generates both the correct response body and the appropriate status code.
Practical Implementation
For Cursor and Cline Users
Add custom instructions to your .cursorrules or project-specific rules file:
## Error Handling
All error responses must follow our API error schema defined in docs/error-schema.md.
When throwing errors in TypeScript:
1. Use custom error classes extending Error
2. Include error code, message, and validation details
3. Use the ErrorResponseBuilder utility from lib/errors
Example:
throw new ValidationError('Email validation failed', {
field: 'email',
details: ['Invalid email format']
});
For Claude Code Users
Create a CLAUDE.md file in your project root with error handling instructions:
# Error Response Requirements
All API error responses must conform to the schema in ./schemas/error-response.json.
Use the ErrorFormatter class for consistent error generation:
import { ErrorFormatter } from './lib/errors';
throw ErrorFormatter.validation('Invalid input', {
fields: { email: 'Must be valid email' }
});
For GitHub Copilot Users
Add inline instructions or create a .github/copilot-instructions.md file:
# Error Response Format
Always generate error responses matching our standard format:
- success: false
- error.code: UPPERCASE_WITH_UNDERSCORES
- error.message: human-readable string
- error.details: array of {field, message} objects when applicable
- error.timestamp: new Date().toISOString()
- error.requestId: generate or use incoming request ID
Tool-by-Tool Configuration Comparison
Different AI tools vary in how persistently they honor custom instructions. Understanding these differences helps you calibrate how detailed your instructions need to be:
| Tool | Config Mechanism | Instruction Persistence | Schema Adherence |
|---|---|---|---|
| Cursor | .cursorrules |
Per-project, always active | High with examples |
| Claude Code | CLAUDE.md |
Per-project, always active | High with examples |
| GitHub Copilot | copilot-instructions.md |
Per-repo | Moderate |
| ChatGPT | Custom Instructions (account) | Account-wide | Moderate |
| Cline | .clinerules |
Per-project | High with examples |
| Windsurf | .windsurfrules |
Per-project | High with examples |
Tools that read project-level config files on every request (Cursor, Claude Code, Cline) provide more consistent adherence than tools that rely on account-level settings or inline prompting. For critical schema enforcement, project-level config files are the most reliable mechanism.
Advanced: TypeScript Type-Driven Instructions
If your project uses TypeScript, embedding your type definitions directly into the custom instructions is the most precise way to communicate your schema. AI models parse TypeScript interface definitions accurately and generate code that satisfies the type contracts:
// Include this in your CLAUDE.md or .cursorrules:
interface ApiError {
code: ErrorCode;
message: string;
details?: ValidationDetail[];
timestamp: string; // ISO 8601
requestId: string; // "req_" prefix required
}
interface ValidationDetail {
field: string;
message: string;
}
type ErrorCode =
| 'VALIDATION_ERROR'
| 'AUTHENTICATION_ERROR'
| 'AUTHORIZATION_ERROR'
| 'NOT_FOUND'
| 'RATE_LIMIT_ERROR'
| 'INTERNAL_ERROR'
| 'EXTERNAL_SERVICE_ERROR';
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: ApiError;
}
With these type definitions in your custom instructions, the AI will generate code that satisfies the type checker automatically—no runtime surprises.
Testing Your Custom Instructions
After adding custom instructions, verify they work by asking AI to generate error handling code. Check for:
-
Consistent structure: All fields present in the correct hierarchy
-
Correct field types: Codes are strings, timestamps are ISO dates, etc.
-
Proper status codes: Matching HTTP codes for each error type
-
Use of utilities: Using your existing error handling functions
A useful verification workflow is to ask the AI to generate error handling for three different endpoint types in a single session: a validation-heavy POST endpoint, a resource-fetching GET endpoint, and an authenticated-only DELETE endpoint. Diffing the error response shapes across all three will reveal any inconsistencies in how your instructions are being interpreted.
If the AI deviates from your schema, refine your instructions with more specific examples or constraints.
Common Pitfalls to Avoid
Being too vague: Instructions like “use good error handling” leave too much room for interpretation. Be specific about every field and format.
Missing edge cases: If your schema handles partial failures differently from complete failures, explain both scenarios in your instructions.
Forgetting validation details: Many APIs include field-level validation errors. Specify whether this is an array of objects or a flat object.
Ignoring language differences: Error handling patterns differ between languages. Provide examples for each language you use.
Omitting the “why”: AI models follow instructions more reliably when the instructions include brief rationale. Adding “so that API consumers can parse errors without branching logic” after your schema definition improves adherence—the model treats the instruction as a meaningful constraint rather than an arbitrary rule.
Not versioning your instructions: Store your .cursorrules, CLAUDE.md, and related files in version control. When your schema evolves, update the instructions at the same time. Drift between your actual schema and your AI instructions is a common source of inconsistent code in growing codebases.
Related Articles
- Writing Custom Instructions That Make AI Follow Your Team’s
- How to Write Custom Instructions That Make AI Respect Your
- How to Write Custom Instructions for AI That Follow Your
- How to Write ChatGPT Custom Instructions
- ChatGPT Custom GPT Not Following Instructions
Built by theluckystrike — More at zovo.one