Loading...
Loading...
Guides error handling in Zhin using the built-in error hierarchy, ErrorManager, RetryManager, and CircuitBreaker. Use when implementing resilient error handling, retry logic, or circuit breaker patterns in Zhin plugins.
npx skill4agent add zhinjs/ai-skills zhin-error-handlingZhinErrorZhinError (base)
├── ConfigError — Configuration issues
├── PluginError — Plugin loading/execution failures
├── AdapterError — Adapter/bot connection issues
├── ConnectionError — Network/connection failures (retryable flag)
├── MessageError — Message processing errors
├── ContextError — Context injection failures
├── ValidationError — Input validation errors
├── PermissionError — Permission/authorization errors
└── TimeoutError — Operation timeout errorsimport {
ZhinError, ConfigError, PluginError, AdapterError,
ConnectionError, MessageError, ContextError,
ValidationError, PermissionError, TimeoutError,
} from '@zhin.js/core'
// Configuration error
throw new ConfigError('Missing API key', { field: 'apiKey' })
// Plugin error with plugin name
throw new PluginError('Failed to initialize', 'my-plugin', { reason: 'missing dep' })
// Adapter error with adapter and bot name
throw new AdapterError('Connection refused', 'discord', 'bot-1')
// Connection error (retryable)
throw new ConnectionError('Server unreachable', true)
// Permission error
throw new PermissionError('Admin required', 'user-123', 'bot_admin')
// Timeout error
throw new TimeoutError('Operation timed out', 30000)try {
// ...
} catch (err) {
if (err instanceof ZhinError) {
console.log(err.toJSON()) // Full JSON representation
console.log(err.toUserString()) // User-friendly: "[CODE] message"
console.log(err.code) // Error code string
console.log(err.timestamp) // When the error occurred
console.log(err.context) // Additional context data
}
}import { errorManager, ErrorHandler } from '@zhin.js/core'
// Register handler for specific error types
errorManager.register('ConnectionError', async (error, context) => {
console.log('Connection issue:', error.message)
// Notify admin, log to database, etc.
})
// Register global handler (called for all errors)
errorManager.registerGlobal(async (error, context) => {
console.log('Error occurred:', error.message)
})
// Handle an error
try {
await riskyOperation()
} catch (error) {
await errorManager.handle(error as Error, { source: 'my-plugin' })
}
// Clean up handlers
errorManager.unregister('ConnectionError', myHandler)
errorManager.clear()import { RetryManager } from '@zhin.js/core'
const result = await RetryManager.retry(
async () => {
// Operation that might fail
return await fetchExternalAPI()
},
{
maxRetries: 3, // Maximum retry attempts
delay: 1000, // Base delay in ms
exponentialBackoff: true, // Double delay each retry
retryCondition: (error) => {
// Only retry ConnectionErrors
return error instanceof ConnectionError && error.retryable
},
}
)exponentialBackoff: truedelay: 1000import { CircuitBreaker } from '@zhin.js/core'
const breaker = new CircuitBreaker(
5, // failureThreshold — open after 5 failures
60000, // timeoutMs — stay open for 60s
10000 // monitoringPeriodMs
)
try {
const result = await breaker.execute(async () => {
return await callExternalService()
})
} catch (error) {
if (error.message === 'Circuit breaker is OPEN') {
// Service is down, use fallback
return fallbackValue
}
throw error
}
// Check state
console.log(breaker.getState()) // 'CLOSED' | 'OPEN' | 'HALF_OPEN'
// Manual reset
breaker.reset()| State | Description |
|---|---|
| Normal operation, requests pass through |
| Too many failures, requests are rejected immediately |
| Timeout expired, one test request is allowed |
import { usePlugin, PluginError, RetryManager } from 'zhin.js'
const plugin = usePlugin()
plugin.onMounted(async () => {
try {
const data = await RetryManager.retry(
() => loadExternalResource(),
{ maxRetries: 3, delay: 2000 }
)
plugin.logger.info('Resource loaded successfully')
} catch (error) {
plugin.logger.error(`Failed to load resource: ${error.message}`)
throw new PluginError('Initialization failed', plugin.name, {
originalError: error.message,
})
}
})ErrorerrorManagerRetryManagerCircuitBreakerConnectionError.retryableonDispose