Error Reference
Standard error codes returned by METAOS tools.
Error Handling Pattern
try {
await tools.calendar.createEvent({ ... });
} catch (error) {
// All errors include: code, message, details
console.error(error.code); // "CAPABILITY_DENIED"
console.error(error.message); // Human-readable description
console.error(error.details); // Additional context
// Return error card to user
return {
type: "error",
title: "Failed to create event",
description: error.message
};
}Standard Error Codes
| Code | Description | Resolution |
|---|---|---|
CAPABILITY_DENIED | User has not granted required capability | Add capability to manifest, request user approval |
SCOPE_VIOLATION | Attempting to access resource outside manifest scopes | Update manifest scopes or restrict access |
APPROVAL_REQUIRED | Action requires user approval via approval.request() | Call approval.request() before the action |
APPROVAL_DENIED | User declined approval request | Inform user and cancel action |
INVALID_PARAMETER | Tool parameter is missing or invalid | Check parameter format and required fields |
INVALID_DATE_RANGE | Start date is after end date | Validate date ordering before calling tool |
INVALID_RECIPIENT | Email address is malformed | Validate email format |
FILE_NOT_FOUND | Storage path does not exist | Check path exists before reading |
RESOURCE_NOT_FOUND | Calendar event, message, or contact not found | Verify resource ID before accessing |
STORAGE_QUOTA_EXCEEDED | User's storage is full | Inform user to free up space |
NETWORK_ERROR | External API call failed | Retry with exponential backoff |
RATE_LIMIT_EXCEEDED | Too many requests to tool API | Implement rate limiting, retry after delay |
INTERNAL_ERROR | Unexpected OS error | Report to support, retry action |
TIMEOUT | Operation took too long | Retry with shorter timeout |
Error Recovery Examples
Permission Denied
try {
await tools.messages.send({ ... });
} catch (error) {
if (error.code === "CAPABILITY_DENIED") {
return {
type: "error",
title: "Permission Required",
description: "Grant this agent 'messages.send' permission to send messages.",
action: {
label: "Grant Permission",
url: "metaos://settings/capabilities"
}
};
}
}Retry on Network Error
async function withRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.code === "NETWORK_ERROR" && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
continue;
}
throw error;
}
}
}
// Usage
const events = await withRetry(() =>
tools.calendar.listEvents({ start, end })
);Graceful Degradation
try {
const contacts = await tools.contacts.search({ name: "Alice" });
// Use contact data
} catch (error) {
if (error.code === "CAPABILITY_DENIED") {
// Fallback: ask user for email manually
return {
type: "suggestion",
title: "Need contact access",
description: "Grant contacts permission or enter email manually",
actions: [
{ label: "Grant Permission", action: "grant_capability" },
{ label: "Enter Email", action: "manual_email" }
]
};
}
}✨ Best Practices
- Always handle CAPABILITY_DENIED and APPROVAL_REQUIRED errors
- Implement retry logic for NETWORK_ERROR and TIMEOUT
- Provide helpful user messaging for permission errors
- Log INTERNAL_ERROR to help with debugging
- Use try/catch around all tool calls