Skip to content

Error Handling

Design Philosophy

The SDK uses a throw channel + return channel hybrid model:

  1. Throw channel — Failures become TopBridgeError subclasses. Callers catch with instanceof.
  2. Return channel — Success (ok / warning) returns SdkResponse<T>. Warnings never block the main flow.
  3. Protocol codes — V2 code values are preserved on error.code for programmatic checks.
  4. Structured metadata — Subclass fields carry UI-ready context (storeUrl, sessions, field, …).

Error Class Hierarchy

TopBridgeError (Base)
├── TopBridgeConnectionError     Connection failed / timed out / App not running
├── TopBridgeAuthError           Not authenticated
│     .code: 'NOT_AUTHENTICATED'
│     .storeUrl? / .downloadUrl?
├── TopBridgeVersionError        App version too low
│     .code: 'UPDATE_REQUIRED'
│     .storeUrl? / .downloadUrl?
├── TopBridgeQuotaError          Entitlement invalid / quota exhausted
│     .code: 'QUOTA_EXHAUSTED'
│     .reason?
├── TopBridgePrintError          Print failed (unclassified server error)
├── TopBridgeConfigError         Invalid client configuration
├── TopBridgeValidationError     Input validation failed
│     .field?
├── TopBridgePrinterError        Printer offline / not configured
│     .code: 'PRINTER_OFFLINE' | 'PRINTER_NOT_CONFIGURED'
├── TopBridgeTemplateError       Template missing
│     .code: 'TEMPLATE_NOT_FOUND'
├── TopBridgeNetworkError        Cloud network disconnected
│     .code: 'NETWORK_DISCONNECTED'
├── TopBridgeSourceError         Source rejected by whitelist
│     .code: 'INVALID_SOURCE'
├── TopBridgePrinterSetupError   Printer setup CRUD failed
│     .code: PrinterSetupErrorCode
└── TopBridgeSessionError        Session limit exceeded (SessionBlocked)
      .code: 'SESSION_LIMIT_EXCEEDED'
      .limit? / .usedSessions? / .sessions?

Breaking change from older docs

UPDATE_REQUIRED is TopBridgeVersionError, not TopBridgeAuthError. Update any err.code === 'UPDATE_REQUIRED' checks under AuthError.

Type-Safe Handling with instanceof

typescript
import {
  TopBridgeConnectionError,
  TopBridgeAuthError,
  TopBridgeVersionError,
  TopBridgeQuotaError,
  TopBridgePrintError,
  TopBridgePrinterError,
  TopBridgePrinterSetupError,
  TopBridgeTemplateError,
  TopBridgeNetworkError,
  TopBridgeSourceError,
  TopBridgeValidationError,
  TopBridgeSessionError,
} from '@appzgatenz/label-print-topbridge-js'

try {
  await client.print.execute({ /* ... */ })
} catch (err) {
  if (err instanceof TopBridgeConnectionError) {
    // App not running — consider client.launch.ensureRunning()
  } else if (err instanceof TopBridgeAuthError) {
    // User is not logged in
  } else if (err instanceof TopBridgeVersionError) {
    if (err.storeUrl) window.open(err.storeUrl)
  } else if (err instanceof TopBridgeSessionError) {
    // Render err.sessions, then:
    // await client.session.kickSession(err.sessions.map(s => s.id))
    // Retry the original call — no re-login required
  } else if (err instanceof TopBridgeQuotaError) {
    // Show err.reason
  } else if (err instanceof TopBridgePrinterError) {
    // Offline or protocol not configured
  } else if (err instanceof TopBridgePrinterSetupError) {
    // Inspect err.code for charset/font/printer setup failures
  } else if (err instanceof TopBridgeTemplateError) {
    // Template not found
  } else if (err instanceof TopBridgeNetworkError) {
    // Cloud disconnected
  } else if (err instanceof TopBridgeSourceError) {
    // Invalid source
  } else if (err instanceof TopBridgeValidationError) {
    // err.field indicates the bad input
  } else if (err instanceof TopBridgePrintError) {
    // Other print failures
  }
}

Error-to-Scenario Mapping

ScenarioError TypeSuggested Handling
App not installed / not runningTopBridgeConnectionErrorclient.launch.ensureRunning()
User not logged inTopBridgeAuthErrorGuide login in TopBridge App
App version too lowTopBridgeVersionErrorOpen err.storeUrl / err.downloadUrl
Session limit exceededTopBridgeSessionErrorShow err.sessions, call kickSession, retry
Print quota exhaustedTopBridgeQuotaErrorDisplay err.reason
Invalid SDK configurationTopBridgeConfigErrorCheck source / constructor options
Printer offline / not configuredTopBridgePrinterErrorCheck connection and protocol
Printer setup CRUD failedTopBridgePrinterSetupErrorBranch on err.code
Template missingTopBridgeTemplateErrorCheck template ID/Code
Cloud network disconnectedTopBridgeNetworkErrorCheck network
Source rejectedTopBridgeSourceErrorUse an allowed source
Invalid products / paramsTopBridgeValidationErrorFix err.field
Print failed (other)TopBridgePrintErrorInspect err.details

Warning Handling

typescript
const result = await client.print.execute({ /* ... */ })
if (result.warnings?.length) {
  for (const w of result.warnings) {
    switch (w.code) {
      case 'DPI_MISMATCH':
        console.warn(`DPI mismatch: ${w.message}`)
        break
      case 'SIZE_MISMATCH':
        console.warn(`Size mismatch: ${w.message}`)
        break
      case 'DATA_FORMAT':
        console.warn(`Data format hint: ${w.message}`)
        break
    }
  }
}
codereasonTrigger Condition
DPI_MISMATCHdpi_mismatchPrinter DPI does not match template DPI, which may cause printed content scaling or alignment offset
SIZE_MISMATCHsize_mismatchTemplate design size does not match the printer's loaded media size, which may cause content to be truncated or offset (currently effective only for Brother printers)
DATA_FORMATnewline_truncatedA text field in the schema contains newlines; SDK automatically truncated to first line

Industry Comparison

SDKBase ClassCodesType Discrimination
Stripe Node.jsStripeErrortypeinstanceof subclasses
Prismaknown request errorscode (e.g. P2002)instanceof + code
TopBridge SDKTopBridgeErrorV2 protocol codeinstanceof subclasses