Documentation Index
Fetch the complete documentation index at: https://mintlify.com/iii-hq/sdk/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The III SDK provides structured error handling across function invocations, WebSocket connections, and trigger registrations. Understanding error types and handling patterns ensures robust distributed applications.
Error Types
Invocation Errors
When calling remote functions, the SDK returns structured error objects:
// Error structure from InvocationResultMessage
type InvocationError = {
code: 'invocation_failed' | 'function_not_found'
message: string
}
// Timeout error
try {
await iii.call('my-function', { data: 'value' }, 5000)
} catch (error) {
// Error: Invocation timeout after 5000ms: my-function
console.error(error.message)
}
Registration Errors
// Duplicate function ID
try {
iii.registerFunction({ id: 'users::get' }, handler)
iii.registerFunction({ id: 'users::get' }, handler) // throws
} catch (error) {
// Error: function id already registered: users::get
}
// Missing required fields
try {
iii.registerFunction({ id: '' }, handler)
} catch (error) {
// Error: id is required
}
Trigger Registration Errors
// Trigger handler errors are communicated via TriggerRegistrationResult
iii.registerTriggerType(
{ id: 'cron', description: 'Cron trigger' },
{
registerTrigger: async (config) => {
if (!config.config.schedule) {
throw new Error('schedule is required')
}
// Error propagated to engine as:
// { code: 'trigger_registration_failed', message: 'schedule is required' }
},
unregisterTrigger: async (config) => {},
}
)
Function Handler Error Handling
Try/Catch in Handlers
Wrap handler logic in try/catch
Catch errors inside your function handlers to return meaningful responses:import { getContext } from 'iii-sdk'
iii.registerFunction({ id: 'users::create' }, async (input) => {
const { logger } = getContext()
try {
// Validate input
if (!input.email) {
logger.warn('Missing email field', { input })
return { error: 'email is required' }
}
// Perform operation
const user = await db.createUser(input)
logger.info('User created', { userId: user.id })
return { success: true, user }
} catch (error) {
logger.error('Failed to create user', { error: error.message, input })
// Return structured error response
if (error.code === 'DUPLICATE_KEY') {
return { error: 'User already exists' }
}
return { error: 'Internal server error' }
}
})
Log errors with context
Use the context logger to attach trace IDs and span IDs automatically:iii.registerFunction({ id: 'process::payment' }, async (input) => {
const { logger, trace } = getContext()
try {
const result = await stripe.charge(input.amount)
return result
} catch (error) {
// Automatically includes trace_id, span_id, function_id
logger.error('Payment failed', {
amount: input.amount,
stripeError: error.code
})
// Add error details to span
trace?.setStatus({ code: SpanStatusCode.ERROR, message: error.message })
trace?.recordException(error)
throw error // Re-throw to return error to caller
}
})
Uncaught Errors
If a handler throws an uncaught error, the SDK automatically catches it and returns an error response to the caller:iii.registerFunction({ id: 'divide' }, async ({ a, b }) => {
return a / b // Will throw if not numbers
})
// Caller receives:
// {
// error: {
// code: 'invocation_failed',
// message: 'Cannot read property of undefined'
// }
// }
Invocation Error Handling
Configuring Timeouts
import { init, DEFAULT_INVOCATION_TIMEOUT_MS } from 'iii-sdk'
// Set default timeout for all invocations
const iii = init('ws://localhost:49134', {
invocationTimeoutMs: 10000 // 10 seconds
})
// Override per-invocation
try {
const result = await iii.call('slow-function', data, 30000) // 30 seconds
} catch (error) {
if (error.message.includes('timeout')) {
console.error('Function took too long')
}
}
Handling Connection Errors
import type { ConnectionStateCallback } from 'iii-sdk'
const handleConnectionState: ConnectionStateCallback = (state) => {
switch (state) {
case 'connected':
console.log('Ready to invoke functions')
break
case 'reconnecting':
console.warn('Connection lost, retrying...')
break
case 'failed':
console.error('Max retries reached, connection failed')
// Implement fallback or alert
break
}
}
iii.onConnectionStateChange(handleConnectionState)
Best Practices
Error Handling Checklist:
- ✅ Always validate input at the start of handlers
- ✅ Use structured error responses (not just strings)
- ✅ Log errors with context using
ctx.logger.error()
- ✅ Set appropriate timeouts for long-running operations
- ✅ Handle connection state changes for resilience
- ✅ Record exceptions in spans for distributed tracing
- ✅ Differentiate between client errors (4xx) and server errors (5xx)
Graceful Degradation
iii.registerFunction({ id: 'get-recommendations' }, async (input) => {
const { logger } = getContext()
try {
// Try ML service first
return await iii.call('ml::recommend', input, 5000)
} catch (error) {
logger.warn('ML service unavailable, using fallback', { error: error.message })
// Fallback to simple logic
return await iii.call('db::popular-items', { limit: 10 })
}
})
Shutdown Error Handling
// Graceful shutdown rejects pending invocations
process.on('SIGTERM', async () => {
console.log('Shutting down...')
await iii.shutdown() // Rejects all pending with 'iii is shutting down'
process.exit(0)
})