Initial commit
This commit is contained in:
503
references/top-errors.md
Normal file
503
references/top-errors.md
Normal file
@@ -0,0 +1,503 @@
|
||||
# Top Errors & Solutions
|
||||
|
||||
Complete reference for common Claude Agent SDK errors and how to fix them.
|
||||
|
||||
---
|
||||
|
||||
## Error #1: CLI Not Found
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Claude Code CLI not installed"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
The SDK requires Claude Code CLI to be installed globally, but it's not found in PATH.
|
||||
|
||||
### Solution
|
||||
```bash
|
||||
npm install -g @anthropic-ai/claude-code
|
||||
```
|
||||
|
||||
Verify installation:
|
||||
```bash
|
||||
which claude-code
|
||||
# Should output: /usr/local/bin/claude-code or similar
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Install CLI before using SDK
|
||||
- Add to project setup documentation
|
||||
- Check CLI availability in CI/CD
|
||||
|
||||
---
|
||||
|
||||
## Error #2: Authentication Failed
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Invalid API key"
|
||||
"Authentication failed"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- ANTHROPIC_API_KEY environment variable not set
|
||||
- API key is invalid or expired
|
||||
- API key has wrong format
|
||||
|
||||
### Solution
|
||||
```bash
|
||||
# Set API key
|
||||
export ANTHROPIC_API_KEY="sk-ant-..."
|
||||
|
||||
# Verify it's set
|
||||
echo $ANTHROPIC_API_KEY
|
||||
```
|
||||
|
||||
Get API key:
|
||||
1. Visit https://console.anthropic.com/
|
||||
2. Navigate to API Keys section
|
||||
3. Create new key
|
||||
4. Copy and save securely
|
||||
|
||||
### Prevention
|
||||
- Use environment variables (never hardcode)
|
||||
- Check key before running
|
||||
- Add to .env.example template
|
||||
- Document setup process
|
||||
|
||||
---
|
||||
|
||||
## Error #3: Permission Denied
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Tool use blocked"
|
||||
"Permission denied for tool: Bash"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Tool not in `allowedTools` array
|
||||
- `permissionMode` is too restrictive
|
||||
- Custom `canUseTool` callback denied execution
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Add tool to allowedTools
|
||||
options: {
|
||||
allowedTools: ["Read", "Write", "Edit", "Bash"] // Add needed tools
|
||||
}
|
||||
|
||||
// Or use less restrictive permission mode
|
||||
options: {
|
||||
permissionMode: "acceptEdits" // Auto-approve edits
|
||||
}
|
||||
|
||||
// Or check canUseTool logic
|
||||
options: {
|
||||
canUseTool: async (toolName, input) => {
|
||||
console.log("Tool requested:", toolName); // Debug
|
||||
return { behavior: "allow" };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Set appropriate `allowedTools` from start
|
||||
- Test permission logic thoroughly
|
||||
- Use `permissionMode: "bypassPermissions"` in CI/CD
|
||||
|
||||
---
|
||||
|
||||
## Error #4: Context Length Exceeded
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Prompt too long"
|
||||
"Context length exceeded"
|
||||
"Too many tokens"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Input prompt exceeds model's context window (200k tokens)
|
||||
- Long conversation without pruning
|
||||
- Large files in context
|
||||
|
||||
### Solution
|
||||
SDK auto-compacts context, but you can:
|
||||
|
||||
```typescript
|
||||
// Fork session to start fresh from a point
|
||||
const forked = query({
|
||||
prompt: "Continue with fresh context",
|
||||
options: {
|
||||
resume: sessionId,
|
||||
forkSession: true // Start fresh
|
||||
}
|
||||
});
|
||||
|
||||
// Or reduce context
|
||||
options: {
|
||||
allowedTools: ["Read", "Grep"], // Limit tools
|
||||
systemPrompt: "Keep responses concise."
|
||||
}
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Use session forking for long tasks
|
||||
- Keep prompts focused
|
||||
- Don't load unnecessary files
|
||||
- Monitor context usage
|
||||
|
||||
---
|
||||
|
||||
## Error #5: Tool Execution Timeout
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Tool did not respond"
|
||||
"Tool execution timeout"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Tool takes too long (>5 minutes default)
|
||||
- Infinite loop in tool implementation
|
||||
- Network timeout for external tools
|
||||
|
||||
### Solution
|
||||
|
||||
For custom tools:
|
||||
```typescript
|
||||
tool("long_task", "Description", schema, async (args) => {
|
||||
// Add timeout
|
||||
const timeout = 60000; // 1 minute
|
||||
const promise = performLongTask(args);
|
||||
const result = await Promise.race([
|
||||
promise,
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error('Timeout')), timeout)
|
||||
)
|
||||
]);
|
||||
return { content: [{ type: "text", text: result }] };
|
||||
})
|
||||
```
|
||||
|
||||
For bash commands:
|
||||
```typescript
|
||||
// Add timeout to bash command
|
||||
command: "timeout 60s long-running-command"
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Set reasonable timeouts
|
||||
- Optimize tool implementations
|
||||
- Use background jobs for long tasks
|
||||
- Test tools independently
|
||||
|
||||
---
|
||||
|
||||
## Error #6: Session Not Found
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Invalid session ID"
|
||||
"Session not found"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Session ID is incorrect
|
||||
- Session expired (old)
|
||||
- Session from different CLI instance
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Ensure session ID captured correctly
|
||||
let sessionId: string | undefined;
|
||||
for await (const message of response) {
|
||||
if (message.type === 'system' && message.subtype === 'init') {
|
||||
sessionId = message.session_id; // Capture here
|
||||
console.log("Session:", sessionId); // Verify
|
||||
}
|
||||
}
|
||||
|
||||
// Use correct session ID
|
||||
query({
|
||||
prompt: "...",
|
||||
options: { resume: sessionId } // Must match exactly
|
||||
});
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Always capture session_id from system init
|
||||
- Store session IDs reliably
|
||||
- Don't rely on sessions lasting indefinitely
|
||||
- Handle session errors gracefully
|
||||
|
||||
---
|
||||
|
||||
## Error #7: MCP Server Connection Failed
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Server connection error"
|
||||
"MCP server not responding"
|
||||
"Failed to connect to MCP server"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Server command/URL incorrect
|
||||
- Server crashed or not running
|
||||
- Network issues (HTTP/SSE servers)
|
||||
- Missing dependencies
|
||||
|
||||
### Solution
|
||||
|
||||
For stdio servers:
|
||||
```typescript
|
||||
// Verify command works independently
|
||||
// Test: npx @modelcontextprotocol/server-filesystem
|
||||
options: {
|
||||
mcpServers: {
|
||||
"filesystem": {
|
||||
command: "npx", // Verify npx is available
|
||||
args: ["@modelcontextprotocol/server-filesystem"],
|
||||
env: {
|
||||
ALLOWED_PATHS: "/path" // Verify path exists
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For HTTP servers:
|
||||
```typescript
|
||||
// Test URL separately
|
||||
const testResponse = await fetch("https://api.example.com/mcp");
|
||||
console.log(testResponse.status); // Should be 200
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Test MCP servers independently before integration
|
||||
- Verify command/URL works
|
||||
- Add error handling for server failures
|
||||
- Use health checks
|
||||
|
||||
---
|
||||
|
||||
## Error #8: Subagent Definition Error
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Invalid AgentDefinition"
|
||||
"Agent configuration error"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Missing required fields (`description` or `prompt`)
|
||||
- Invalid `model` value
|
||||
- Invalid `tools` array
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
agents: {
|
||||
"my-agent": {
|
||||
description: "Clear description of when to use", // Required
|
||||
prompt: "Detailed system prompt", // Required
|
||||
tools: ["Read", "Write"], // Optional
|
||||
model: "sonnet" // Optional
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Always include `description` and `prompt`
|
||||
- Use TypeScript types
|
||||
- Test agent definitions
|
||||
- Follow examples in templates
|
||||
|
||||
---
|
||||
|
||||
## Error #9: Settings File Not Found
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Cannot read settings"
|
||||
"Settings file not found"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- `settingSources` includes non-existent file
|
||||
- File path incorrect
|
||||
- File permissions deny read
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Check file exists before loading
|
||||
import fs from 'fs';
|
||||
|
||||
const projectSettingsPath = '.claude/settings.json';
|
||||
const settingSources = [];
|
||||
|
||||
if (fs.existsSync(projectSettingsPath)) {
|
||||
settingSources.push('project');
|
||||
}
|
||||
|
||||
options: {
|
||||
settingSources // Only existing files
|
||||
}
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Check file exists before including in sources
|
||||
- Use empty array for isolated execution
|
||||
- Handle missing files gracefully
|
||||
|
||||
---
|
||||
|
||||
## Error #10: Tool Name Collision
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Duplicate tool name"
|
||||
"Tool already defined"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Two MCP servers define same tool name
|
||||
- Tool name conflicts with built-in tool
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Use unique tool names
|
||||
const server1 = createSdkMcpServer({
|
||||
name: "service-a",
|
||||
tools: [
|
||||
tool("service_a_process", ...) // Prefix with server name
|
||||
]
|
||||
});
|
||||
|
||||
const server2 = createSdkMcpServer({
|
||||
name: "service-b",
|
||||
tools: [
|
||||
tool("service_b_process", ...) // Different name
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Use unique tool names
|
||||
- Prefix tools with server name
|
||||
- Test integration before deployment
|
||||
|
||||
---
|
||||
|
||||
## Error #11: Zod Schema Validation Error
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Invalid tool input"
|
||||
"Schema validation failed"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Agent provided data that doesn't match Zod schema
|
||||
- Schema too restrictive
|
||||
- Missing `.describe()` on fields
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Add descriptive schemas
|
||||
{
|
||||
email: z.string().email().describe("User email address"),
|
||||
age: z.number().int().min(0).max(120).describe("Age in years"),
|
||||
role: z.enum(["admin", "user"]).describe("User role")
|
||||
}
|
||||
|
||||
// Make fields optional if appropriate
|
||||
{
|
||||
email: z.string().email(),
|
||||
phoneOptional: z.string().optional() // Not required
|
||||
}
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Use `.describe()` on all fields
|
||||
- Add validation constraints
|
||||
- Test with various inputs
|
||||
- Make optional fields explicit
|
||||
|
||||
---
|
||||
|
||||
## Error #12: Filesystem Permission Denied
|
||||
|
||||
### Error Message
|
||||
```
|
||||
"Access denied"
|
||||
"Cannot access path"
|
||||
"EACCES: permission denied"
|
||||
```
|
||||
|
||||
### Why It Happens
|
||||
- Path outside `workingDirectory`
|
||||
- No read/write permissions
|
||||
- Protected system directory
|
||||
|
||||
### Solution
|
||||
```typescript
|
||||
// Set correct working directory
|
||||
options: {
|
||||
workingDirectory: "/path/to/accessible/dir"
|
||||
}
|
||||
|
||||
// Or fix permissions
|
||||
// chmod +r file.txt (add read)
|
||||
// chmod +w file.txt (add write)
|
||||
```
|
||||
|
||||
### Prevention
|
||||
- Set appropriate `workingDirectory`
|
||||
- Verify file permissions
|
||||
- Don't access system directories
|
||||
- Use dedicated project directories
|
||||
|
||||
---
|
||||
|
||||
## General Error Handling Pattern
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const response = query({ prompt: "...", options: { ... } });
|
||||
|
||||
for await (const message of response) {
|
||||
if (message.type === 'error') {
|
||||
console.error('Agent error:', message.error);
|
||||
// Handle non-fatal errors
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fatal error:', error);
|
||||
|
||||
// Handle specific errors
|
||||
switch (error.code) {
|
||||
case 'CLI_NOT_FOUND':
|
||||
console.error('Install: npm install -g @anthropic-ai/claude-code');
|
||||
break;
|
||||
case 'AUTHENTICATION_FAILED':
|
||||
console.error('Check ANTHROPIC_API_KEY');
|
||||
break;
|
||||
case 'RATE_LIMIT_EXCEEDED':
|
||||
console.error('Rate limited. Retry with backoff.');
|
||||
break;
|
||||
case 'CONTEXT_LENGTH_EXCEEDED':
|
||||
console.error('Reduce context or fork session');
|
||||
break;
|
||||
default:
|
||||
console.error('Unexpected error:', error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**For more details**: See SKILL.md
|
||||
**Template**: templates/error-handling.ts
|
||||
Reference in New Issue
Block a user