Files
2025-11-30 08:23:58 +08:00

504 lines
9.8 KiB
Markdown

# 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