Error Handling
Handle errors gracefully with the Cobbl SDK
The SDK throws CobblError for all error cases. This provides a consistent way to handle errors across your application.
Error handling works the same for both CobblAdminClient and CobblPublicClient.
CobblError
All SDK errors are instances of CobblError:
import { CobblError } from '@cobbl-ai/sdk'
try {
const result = await adminClient.runPrompt('my-prompt', { topic: 'test' })
} catch (error) {
if (error instanceof CobblError) {
console.error(`Error [${error.code}]: ${error.message}`)
}
}Error Properties
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error message |
code | CobblErrorCode | Machine-readable error code |
details | unknown | Additional error details (optional) |
Utility Methods
isCobblError
Static method to check if an error is a CobblError:
import { CobblError } from '@cobbl-ai/sdk'
try {
await adminClient.runPrompt('my-prompt', {})
} catch (error) {
if (CobblError.isCobblError(error)) {
// TypeScript knows error is CobblError here
console.error(`Error code: ${error.code}`)
}
}toJSON
Convert the error to a JSON-serializable object for logging or transmission:
try {
await adminClient.runPrompt('my-prompt', {})
} catch (error) {
if (error instanceof CobblError) {
// Serialize for structured logging
console.error(JSON.stringify(error.toJSON()))
// => { "name": "CobblError", "message": "...", "code": "NOT_FOUND", "details": {...} }
}
}Error Codes
| Code | Description |
|---|---|
INVALID_CONFIG | Invalid SDK configuration |
INVALID_REQUEST | Malformed request (missing required fields) |
UNAUTHORIZED | Invalid or missing API key |
FORBIDDEN | Prompt is disabled or access is forbidden |
NOT_FOUND | Resource not found (prompt doesn't exist) |
ARCHIVED | Prompt has been archived |
RATE_LIMIT_EXCEEDED | Too many requests |
SERVER_ERROR | Server-side error |
NETWORK_ERROR | Network connectivity issue |
API_ERROR | Other API errors |
Handling Specific Errors
With CobblAdminClient
See CobblAdminClient for more details on running prompts.
import { CobblAdminClient, CobblError } from '@cobbl-ai/sdk'
try {
const result = await adminClient.runPrompt('my-prompt', { topic: 'test' })
} catch (error) {
if (error instanceof CobblError) {
switch (error.code) {
case 'UNAUTHORIZED':
console.error('Invalid API key - check your configuration')
break
case 'FORBIDDEN':
console.error('Prompt is disabled - enable it in the dashboard')
break
case 'NOT_FOUND':
console.error('Prompt not found - verify the prompt slug')
break
case 'ARCHIVED':
console.error('Prompt has been archived - restore it or use another')
break
case 'INVALID_REQUEST':
console.error('Invalid request:', error.details)
break
case 'RATE_LIMIT_EXCEEDED':
console.error('Rate limit exceeded - try again later')
// Implement retry with backoff
break
case 'NETWORK_ERROR':
console.error('Network error - check your connection')
break
case 'SERVER_ERROR':
console.error('Server error - please try again')
break
default:
console.error('Unexpected error:', error.message)
}
} else {
console.error('Unknown error:', error)
}
}With CobblPublicClient
See CobblPublicClient for more details on collecting feedback.
import { CobblPublicClient, CobblError } from '@cobbl-ai/sdk'
try {
await publicClient.createFeedback({
runId: 'run_abc123',
helpful: 'helpful',
})
} catch (error) {
if (error instanceof CobblError) {
switch (error.code) {
case 'NOT_FOUND':
console.error('Run ID not found - it may have expired')
break
case 'INVALID_REQUEST':
console.error('Invalid feedback data:', error.details)
break
default:
console.error('Failed to submit feedback:', error.message)
}
}
}Graceful Fallbacks
Always provide fallback behavior for critical paths:
const generateGreeting = async (userName: string): Promise<string> => {
try {
const result = await adminClient.runPrompt('greeting', { name: userName })
return result.output
} catch (error) {
// Log for debugging
console.error('Failed to generate greeting:', error)
// Return fallback content
return `Hello, ${userName}! Welcome to our platform.`
}
}Retry Logic
For transient errors, implement retry with exponential backoff:
const runPromptWithRetry = async (
slug: string,
input: Record<string, string>,
maxRetries = 3
) => {
let lastError: Error | undefined
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await adminClient.runPrompt(slug, input)
} catch (error) {
if (error instanceof CobblError) {
// Don't retry client errors
if (['UNAUTHORIZED', 'FORBIDDEN', 'NOT_FOUND', 'ARCHIVED', 'INVALID_REQUEST'].includes(error.code)) {
throw error
}
// Retry server/network errors
lastError = error
const delay = Math.pow(2, attempt) * 1000 // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay))
} else {
throw error
}
}
}
throw lastError
}Framework Examples
Express.js Error Middleware
import { CobblError } from '@cobbl-ai/sdk'
const errorHandler = (
error: Error,
req: express.Request,
res: express.Response,
next: express.NextFunction
) => {
if (error instanceof CobblError) {
switch (error.code) {
case 'UNAUTHORIZED':
case 'FORBIDDEN':
return res.status(403).json({ error: 'Access denied' })
case 'NOT_FOUND':
return res.status(404).json({ error: 'Resource not found' })
case 'RATE_LIMIT_EXCEEDED':
return res.status(429).json({ error: 'Too many requests' })
default:
return res.status(500).json({ error: 'Internal server error' })
}
}
return res.status(500).json({ error: 'An unexpected error occurred' })
}
app.use(errorHandler)Next.js API Route
import { CobblAdminClient, CobblError } from '@cobbl-ai/sdk'
import { NextResponse } from 'next/server'
const adminClient = new CobblAdminClient({
apiKey: process.env.COBBL_API_KEY!,
})
export const POST = async (request: Request) => {
try {
const body = await request.json()
const result = await adminClient.runPrompt('generator', body)
return NextResponse.json(result)
} catch (error) {
if (error instanceof CobblError) {
const status = {
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
RATE_LIMIT_EXCEEDED: 429,
}[error.code] ?? 500
return NextResponse.json(
{ error: error.message, code: error.code },
{ status }
)
}
return NextResponse.json(
{ error: 'An unexpected error occurred' },
{ status: 500 }
)
}
}Logging Best Practices
Log errors with context for debugging:
import { CobblError } from '@cobbl-ai/sdk'
try {
const result = await adminClient.runPrompt(slug, input)
} catch (error) {
if (error instanceof CobblError) {
console.error({
message: 'Prompt execution failed',
code: error.code,
errorMessage: error.message,
details: error.details,
promptSlug: slug,
// Don't log sensitive input values in production
})
}
throw error
}