Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DecartAI/sdk/llms.txt
Use this file to discover all available pages before exploring further.
The Decart AI SDK provides structured error handling with specific error codes for different failure scenarios. This guide shows you how to handle errors gracefully.
Error Types
All SDK errors follow the DecartSDKError type:
type DecartSDKError = {
code: string;
message: string;
data?: Record<string, unknown>;
cause?: Error;
};
Error Codes
The SDK defines these error codes:
export const ERROR_CODES = {
// General errors
INVALID_API_KEY: "INVALID_API_KEY",
INVALID_BASE_URL: "INVALID_BASE_URL",
PROCESSING_ERROR: "PROCESSING_ERROR",
INVALID_INPUT: "INVALID_INPUT",
INVALID_OPTIONS: "INVALID_OPTIONS",
MODEL_NOT_FOUND: "MODEL_NOT_FOUND",
// Queue API errors
QUEUE_SUBMIT_ERROR: "QUEUE_SUBMIT_ERROR",
QUEUE_STATUS_ERROR: "QUEUE_STATUS_ERROR",
QUEUE_RESULT_ERROR: "QUEUE_RESULT_ERROR",
JOB_NOT_COMPLETED: "JOB_NOT_COMPLETED",
// Token errors
TOKEN_CREATE_ERROR: "TOKEN_CREATE_ERROR",
// WebRTC errors (real-time)
WEBRTC_WEBSOCKET_ERROR: "WEBRTC_WEBSOCKET_ERROR",
WEBRTC_ICE_ERROR: "WEBRTC_ICE_ERROR",
WEBRTC_TIMEOUT_ERROR: "WEBRTC_TIMEOUT_ERROR",
WEBRTC_SERVER_ERROR: "WEBRTC_SERVER_ERROR",
WEBRTC_SIGNALING_ERROR: "WEBRTC_SIGNALING_ERROR",
};
Basic Error Handling
Process API (Synchronous)
import { createDecartClient, models, ERROR_CODES } from "@decartai/sdk";
try {
const client = createDecartClient({ apiKey: "your-api-key" });
const blob = await client.process({
model: models.image("lucy-pro-t2i"),
prompt: "a beautiful sunset",
});
console.log("Image generated successfully");
} catch (error) {
// Type guard to check if it's a DecartSDKError
if (typeof error === 'object' && error !== null && 'code' in error) {
const sdkError = error as { code: string; message: string };
switch (sdkError.code) {
case ERROR_CODES.INVALID_API_KEY:
console.error("Invalid API key. Please check your credentials.");
break;
case ERROR_CODES.INVALID_INPUT:
console.error("Invalid input:", sdkError.message);
break;
case ERROR_CODES.PROCESSING_ERROR:
console.error("Processing failed:", sdkError.message);
break;
default:
console.error("Unexpected error:", sdkError.message);
}
} else {
console.error("Unknown error:", error);
}
}
Queue API (Async Jobs)
try {
const job = await client.queue.submit({
model: models.video("lucy-pro-t2v"),
prompt: "a flying bird",
});
console.log("Job submitted:", job.job_id);
// Poll for status
const status = await client.queue.status(job.job_id);
console.log("Job status:", status.status);
// Get result (only when completed)
if (status.status === "completed") {
const blob = await client.queue.result(job.job_id);
console.log("Video ready");
}
} catch (error) {
if (typeof error === 'object' && error !== null && 'code' in error) {
const sdkError = error as { code: string; message: string; data?: any };
switch (sdkError.code) {
case ERROR_CODES.QUEUE_SUBMIT_ERROR:
console.error("Failed to submit job:", sdkError.message);
if (sdkError.data?.status) {
console.error("HTTP status:", sdkError.data.status);
}
break;
case ERROR_CODES.JOB_NOT_COMPLETED:
console.error("Job not ready yet:", sdkError.message);
console.error("Current status:", sdkError.data?.currentStatus);
break;
default:
console.error("Queue error:", sdkError.message);
}
}
}
Real-Time Error Handling
For real-time connections, handle errors via the event emitter:
import { createDecartClient, type DecartSDKError, ERROR_CODES } from "@decartai/sdk";
const client = createDecartClient({ apiKey: "your-api-key" });
try {
const realtimeClient = await client.realtime.connect(stream, {
model: models.realtime("mirage_v2"),
onRemoteStream: (transformedStream) => {
console.log("Receiving video stream");
},
});
// Subscribe to connection errors
realtimeClient.on("error", (error: DecartSDKError) => {
console.error("WebRTC error:", error.code, error.message);
switch (error.code) {
case ERROR_CODES.WEBRTC_WEBSOCKET_ERROR:
console.error("WebSocket connection failed");
// Try reconnecting or show user message
break;
case ERROR_CODES.WEBRTC_ICE_ERROR:
console.error("ICE connection failed (network issue)");
// Check network/firewall settings
break;
case ERROR_CODES.WEBRTC_TIMEOUT_ERROR:
console.error("Connection timed out");
if (error.data?.timeoutMs) {
console.error(`Timeout after ${error.data.timeoutMs}ms`);
}
// Retry connection
break;
case ERROR_CODES.WEBRTC_SERVER_ERROR:
console.error("Server error:", error.message);
// Server-side issue, wait and retry
break;
default:
console.error("Unhandled WebRTC error");
}
});
// Monitor connection state
realtimeClient.on("connectionChange", (state) => {
console.log("Connection state:", state);
if (state === "disconnected") {
console.log("Connection lost");
} else if (state === "reconnecting") {
console.log("Attempting to reconnect...");
}
});
} catch (error) {
console.error("Failed to establish connection:", error);
}
Diagnostic Events
For real-time connections, you can also listen to diagnostic events:
realtimeClient.on("diagnostic", (event) => {
console.log("Diagnostic event:", event.name, event.data);
if (event.name === "videoStall") {
if (event.data.stalled) {
console.warn("Video stream stalled");
} else {
console.log(`Video recovered after ${event.data.durationMs}ms`);
}
}
});
Retry Strategies
Exponential Backoff
async function generateWithRetry(
client: DecartClient,
options: ProcessOptions,
maxRetries = 3
) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.process(options);
} catch (error) {
lastError = error;
// Don't retry on invalid input or API key
if (typeof error === 'object' && error !== null && 'code' in error) {
const sdkError = error as { code: string };
if (
sdkError.code === ERROR_CODES.INVALID_API_KEY ||
sdkError.code === ERROR_CODES.INVALID_INPUT
) {
throw error;
}
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
console.log(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
// Usage
try {
const blob = await generateWithRetry(client, {
model: models.image("lucy-pro-t2i"),
prompt: "a sunset",
});
} catch (error) {
console.error("Failed after retries:", error);
}
Queue Polling with Timeout
async function pollJobWithTimeout(
client: DecartClient,
jobId: string,
timeoutMs = 300000 // 5 minutes
) {
const startTime = Date.now();
while (true) {
if (Date.now() - startTime > timeoutMs) {
throw new Error(`Job ${jobId} timed out after ${timeoutMs}ms`);
}
try {
const status = await client.queue.status(jobId);
if (status.status === "completed") {
return await client.queue.result(jobId);
}
if (status.status === "failed") {
throw new Error(`Job failed: ${status.error}`);
}
// Wait before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
} catch (error) {
console.error("Error polling job:", error);
throw error;
}
}
}
// Usage
try {
const job = await client.queue.submit({
model: models.video("lucy-pro-t2v"),
prompt: "flying bird",
});
const blob = await pollJobWithTimeout(client, job.job_id);
console.log("Video ready");
} catch (error) {
console.error("Video generation failed:", error);
}
React Error Boundaries
For React applications, use error boundaries to catch rendering errors:
import { Component, type ReactNode } from "react";
interface Props {
children: ReactNode;
fallback: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: any) {
console.error("Error caught by boundary:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
// Usage
function App() {
return (
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<VideoStream prompt="anime style" />
</ErrorBoundary>
);
}
Best Practices
- Always handle errors - Never ignore try/catch blocks
- Check error codes - Use specific error codes to provide better feedback
- Retry transient errors - Network issues, timeouts, etc.
- Don’t retry permanent errors - Invalid API keys, bad input, etc.
- Log errors - Keep track of failures for debugging
- Show user-friendly messages - Don’t expose technical details to users
- Monitor connection state - React to state changes in real-time connections
- Use diagnostic events - Track video stalls and other issues
- Set timeouts - Don’t wait indefinitely for responses
- Clean up resources - Disconnect clients, revoke object URLs, etc.
Next Steps