Early Beta — The Web SDK is in early beta. APIs may change between releases.
Overview
The RunAnywhere Web SDK provides structured error handling through SDKError with specific error codes. This guide covers error types, handling patterns, and recovery strategies.
SDKError Structure
import { SDKError, SDKErrorCode } from '@runanywhere/web'
class SDKError extends Error {
readonly code: SDKErrorCode
readonly details?: string
readonly message: string
}
Checking for SDK Errors
import { SDKError, SDKErrorCode } from '@runanywhere/web'
import { TextGeneration } from '@runanywhere/web-llamacpp'
try {
const { stream, result } = await TextGeneration.generateStream('Hello', { maxTokens: 100 })
for await (const token of stream) {
/* ... */
}
} catch (err) {
if (err instanceof SDKError) {
console.log('Code:', err.code)
console.log('Message:', err.message)
console.log('Details:', err.details)
} else {
console.error('Unexpected error:', err)
}
}
Error Codes
Initialization Errors
| Code | Value | Description | Recovery |
|---|
NotInitialized | -100 | SDK not initialized | Call RunAnywhere.initialize() |
AlreadyInitialized | -101 | SDK already initialized | Use existing instance or reset() |
InvalidConfiguration | -102 | Invalid config options | Check initialization options |
InitializationFailed | -103 | Init failed | Check browser compatibility |
Model Errors
| Code | Value | Description | Recovery |
|---|
ModelNotFound | -110 | Model not in registry | Register model first |
ModelLoadFailed | -111 | Failed to load model | Check model path, format |
ModelInvalidFormat | -112 | Unsupported format | Use GGUF or ONNX |
ModelNotLoaded | -113 | No model loaded | Call ModelManager.loadModel() first |
Generation Errors
| Code | Value | Description | Recovery |
|---|
GenerationFailed | -130 | Text generation failed | Check model, reduce tokens |
GenerationCancelled | -131 | Generation cancelled | Expected if cancel() called |
GenerationTimeout | -132 | Generation timed out | Reduce maxTokens |
Download Errors
| Code | Value | Description | Recovery |
|---|
DownloadFailed | -160 | Download failed | Check network, CORS headers |
Storage Errors
| Code | Value | Description | Recovery |
|---|
StorageError | -180 | Storage operation failed | Check OPFS availability |
WASM Errors
| Code | Value | Description | Recovery |
|---|
WASMLoadFailed | -900 | WASM module failed to load | Check WASM file paths, bundler config |
WASMNotLoaded | -901 | WASM module not loaded | Register backends first |
Static Factory Methods
SDKError provides convenient factory methods:
SDKError.notInitialized()
SDKError.wasmNotLoaded()
SDKError.modelNotFound('my-model')
SDKError.generationFailed('Context window exceeded')
SDKError.fromRACResult(resultCode, 'details')
Handling Patterns
Basic Error Handling
import { SDKError, SDKErrorCode } from '@runanywhere/web'
import { TextGeneration } from '@runanywhere/web-llamacpp'
try {
const { stream } = await TextGeneration.generateStream(prompt, { maxTokens: 200 })
for await (const token of stream) {
/* update UI */
}
} catch (err) {
if (err instanceof SDKError) {
switch (err.code) {
case SDKErrorCode.NotInitialized:
console.error('SDK not initialized — call RunAnywhere.initialize() first')
break
case SDKErrorCode.ModelNotLoaded:
console.error('No model loaded — call ModelManager.loadModel() first')
break
case SDKErrorCode.GenerationFailed:
console.error('Generation failed:', err.details)
break
case SDKErrorCode.GenerationCancelled:
break
default:
console.error(`SDK error [${err.code}]: ${err.message}`)
}
}
}
WASM Memory Crash Handling
VLM inference can occasionally trigger WASM memory errors. These are recoverable:
import { VLMWorkerBridge } from '@runanywhere/web-llamacpp'
try {
const result = await VLMWorkerBridge.shared.process(rgbPixels, width, height, prompt, options)
} catch (err) {
const msg = (err as Error).message
if (msg.includes('memory access out of bounds') || msg.includes('RuntimeError')) {
// Recoverable — skip this frame and retry
console.warn('WASM crash, will retry next frame')
} else {
throw err
}
}
WASM Binary Served as HTML (Production)
In production, if your server has a SPA catch-all route that serves index.html for unknown paths, .wasm file requests will return HTML instead of the binary. The WASM compiler receives HTML bytes and throws:
CompileError: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 44 4f
The bytes 3c 21 44 4f decode to <!DO — the start of an HTML document. Fix: ensure static asset serving (with correct MIME types) comes before SPA catch-all routing. See Installation troubleshooting.
Camera “source width is 0”
Calling VideoCapture.captureFrame() before the video stream is fully initialized causes:
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0.
Fix: Wait for the video element’s loadedmetadata event or check videoElement.videoWidth > 0 before capturing. See VLM camera readiness.
VLM Worker “non-JavaScript MIME type”
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html"
The VLM Web Worker URL is resolving to your SPA’s index.html. Fix:
- Use
COEP: credentialless (not require-corp)
- Ensure
.js files are served as static assets before the catch-all route
- Add
worker: { format: 'es' } to your Vite config
Retry Logic
async function withRetry<T>(operation: () => Promise<T>, maxRetries = 2): Promise<T> {
let lastError: Error | null = null
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await operation()
} catch (err) {
lastError = err as Error
if (!(err instanceof SDKError)) throw err
if (
[
SDKErrorCode.NotInitialized,
SDKErrorCode.ModelNotFound,
SDKErrorCode.ModelInvalidFormat,
SDKErrorCode.GenerationCancelled,
].includes(err.code)
) {
throw err
}
if (attempt < maxRetries) {
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)))
continue
}
}
}
throw lastError
}
User-Friendly Messages
function getUserMessage(err: SDKError): string {
switch (err.code) {
case SDKErrorCode.NotInitialized:
return 'The AI system is still loading. Please wait.'
case SDKErrorCode.ModelNotLoaded:
return 'No AI model is loaded. Please download a model first.'
case SDKErrorCode.GenerationFailed:
return 'Failed to generate a response. Please try again.'
case SDKErrorCode.GenerationCancelled:
return 'Response generation was cancelled.'
case SDKErrorCode.WASMLoadFailed:
return 'Failed to load the AI engine. Please refresh the page.'
case SDKErrorCode.DownloadFailed:
return 'Model download failed. Check your internet connection.'
case SDKErrorCode.StorageError:
return 'Storage error. Try clearing browser data and reloading.'
default:
return err.message || 'An unexpected error occurred.'
}
}
React Error Hook
import { useState, useCallback } from 'react'
import { SDKError, SDKErrorCode } from '@runanywhere/web'
export function useSDKError() {
const [error, setError] = useState<SDKError | null>(null)
const handleError = useCallback((err: unknown) => {
if (err instanceof SDKError) {
setError(err)
} else {
console.error('Unexpected error:', err)
}
}, [])
const clearError = useCallback(() => setError(null), [])
const canRetry = error
? ![
SDKErrorCode.NotInitialized,
SDKErrorCode.ModelNotFound,
SDKErrorCode.WASMNotLoaded,
].includes(error.code)
: false
return { error, handleError, clearError, canRetry }
}
Logging Errors
import { SDKLogger, LogLevel } from '@runanywhere/web'
SDKLogger.level = LogLevel.Error
try {
const { stream } = await TextGeneration.generateStream(prompt)
for await (const token of stream) {
/* ... */
}
} catch (err) {
if (err instanceof SDKError) {
console.error(`[${err.code}] ${err.message}`, err.details)
}
}