Skip to main content
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

CodeValueDescriptionRecovery
NotInitialized-100SDK not initializedCall RunAnywhere.initialize()
AlreadyInitialized-101SDK already initializedUse existing instance or reset()
InvalidConfiguration-102Invalid config optionsCheck initialization options
InitializationFailed-103Init failedCheck browser compatibility

Model Errors

CodeValueDescriptionRecovery
ModelNotFound-110Model not in registryRegister model first
ModelLoadFailed-111Failed to load modelCheck model path, format
ModelInvalidFormat-112Unsupported formatUse GGUF or ONNX
ModelNotLoaded-113No model loadedCall ModelManager.loadModel() first

Generation Errors

CodeValueDescriptionRecovery
GenerationFailed-130Text generation failedCheck model, reduce tokens
GenerationCancelled-131Generation cancelledExpected if cancel() called
GenerationTimeout-132Generation timed outReduce maxTokens

Download Errors

CodeValueDescriptionRecovery
DownloadFailed-160Download failedCheck network, CORS headers

Storage Errors

CodeValueDescriptionRecovery
StorageError-180Storage operation failedCheck OPFS availability

WASM Errors

CodeValueDescriptionRecovery
WASMLoadFailed-900WASM module failed to loadCheck WASM file paths, bundler config
WASMNotLoaded-901WASM module not loadedRegister 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:
  1. Use COEP: credentialless (not require-corp)
  2. Ensure .js files are served as static assets before the catch-all route
  3. 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

useSDKError.ts
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)
  }
}