Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Error Type Guards - Zagora
Skip to content

Error Type Guards

Narrow error types with utilities

Zagora provides type guard utilities to help narrow error types in your code.

Available Guards

Import guards from zagora/errors:

import { 
  isValidationError,
  isInternalError,
  isDefinedError,
  isZagoraError
} from 'zagora/errors';

isValidationError

Check if an error is a validation error (input, output, or error payload validation failed):

const result = myProcedure(invalidInput);
 
if (!result.ok) {
  if (isValidationError(result.error)) {
    // result.error.kind === 'VALIDATION_ERROR'
    console.log(result.error.issues);
    console.log(result.error.key); // undefined or error key if error helper validation failed
  }
}

isInternalError

Check if an error is an unknown/internal error (unhandled exception in handler):

if (!result.ok) {
  if (isInternalError(result.error)) {
    // result.error.kind === 'UNKNOWN_ERROR'
    console.log(result.error.message);
    console.log(result.error.cause);
  }
}

isDefinedError

Check if an error is one of your defined error types:

const proc = zagora()
  .errors({
    NOT_FOUND: z.object({ id: z.string() }),
    FORBIDDEN: z.object({ reason: z.string() })
  })
  .handler(/* ... */)
  .callable();
 
const result = proc();
 
if (!result.ok) {
  if (isDefinedError(result.error)) {
    // result.error.kind is 'NOT_FOUND' | 'FORBIDDEN'
    switch (result.error.kind) {
      case 'NOT_FOUND':
        console.log(result.error.id);
        break;
      case 'FORBIDDEN':
        console.log(result.error.reason);
        break;
    }
  }
}

isZagoraError

Check if an error is any Zagora error type:

if (!result.ok) {
  if (isZagoraError(result.error)) {
    // It's a Zagora-managed error (not a raw throw)
    console.log(result.error.kind);
  }
}

Pattern: Error Handler Utility

Create a reusable error handler:

import { isValidationError, isInternalError } from 'zagora/errors';
 
function handleError(error) {
  if (isValidationError(error)) {
    return {
      status: 400,
      body: { 
        message: 'Invalid input',
        issues: error.issues 
      }
    };
  }
  
  if (isInternalError(error)) {
    console.error('Internal error:', error.cause);
    return {
      status: 500,
      body: { message: 'Internal server error' }
    };
  }
  
  // Defined error
  return {
    status: 422,
    body: { 
      code: error.kind,
      ...error 
    }
  };
}
 
const result = myProcedure(input);
if (!result.ok) {
  return handleError(result.error);
}

TypeScript Narrowing

The guards work with TypeScript's control flow analysis:

const result = proc();
 
if (!result.ok) {
  const error = result.error;
  
  if (isValidationError(error)) {
    // TypeScript knows: error.kind === 'VALIDATION_ERROR'
    error.issues;  // OK
  } else if (isInternalError(error)) {
    // TypeScript knows: error.kind === 'UNKNOWN_ERROR'
    error.cause;  // OK
  } else {
    // TypeScript knows: it's a defined error
    error.kind;  // 'NOT_FOUND' | 'FORBIDDEN' | ...
  }
}

Next Steps