or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mderror-handling.mdhttp-client.mdindex.mdnetwork-transport.mdobservability.mdpipeline.mdrequest-processing.mdretry-policies.mdutilities.md
tile.json

error-handling.mddocs/

Error Handling

Comprehensive error handling with REST-specific error types, context information, and type guards for robust error management in HTTP operations.

Capabilities

RestError Interface

Primary error type for HTTP request failures with rich context and standard error codes.

/**
 * A custom error type for failed pipeline requests
 */
interface RestError extends Error {
  /**
   * The error code, if available
   */
  code?: string;
  
  /**
   * The HTTP status code of the request, if applicable
   */
  statusCode?: number;
  
  /**
   * The request that was made
   */
  request?: PipelineRequest;
  
  /**
   * The response received, if any
   */
  response?: PipelineResponse;
}

/**
 * RestError constructor interface with error codes
 */
interface RestErrorConstructor {
  /**
   * Something went wrong when making the request.
   * This means the actual request failed for some reason,
   * such as a DNS issue or the connection being lost.
   */
  readonly REQUEST_SEND_ERROR: string;

  /**
   * This means that parsing the response from the server failed.
   * It may have been malformed.
   */
  readonly PARSE_ERROR: string;

  /**
   * Creates a new RestError instance
   * @param message - The error message
   * @param options - Additional options for the error
   */
  new (message: string, options?: RestErrorOptions): RestError;
}

/**
 * The RestError constructor
 */
const RestError: RestErrorConstructor;

interface RestErrorOptions {
  /**
   * The code of the error itself (use statics on RestError if possible)
   */
  code?: string;
  
  /**
   * The HTTP status code of the request (if applicable)
   */
  statusCode?: number;
  
  /**
   * The request that was made
   */
  request?: PipelineRequest;
  
  /**
   * The response received (if any)
   */
  response?: PipelineResponse;
}

Usage Examples:

import { RestError, type RestErrorOptions } from "@azure/core-rest-pipeline";

// Handle RestError in request processing
try {
  const response = await pipeline.sendRequest(client, request);
  console.log(response.bodyAsText);
} catch (error) {
  if (error instanceof RestError) {
    console.error(`Request failed with status ${error.statusCode}`);
    console.error(`Error code: ${error.code}`);
    console.error(`Request URL: ${error.request?.url}`);
    console.error(`Response headers:`, error.response?.headers.toJSON());
  }
}

// Create custom RestError
const customError = new RestError("Custom request failed", {
  code: "CUSTOM_ERROR",
  statusCode: 400,
  request: myRequest,
  response: myResponse
});

// Use standard error codes
const networkError = new RestError("Network connection failed", {
  code: RestError.REQUEST_SEND_ERROR
});

const parseError = new RestError("Response parsing failed", {
  code: RestError.PARSE_ERROR
});

Error Type Guard

Type guard function to check if an error is a RestError instance.

/**
 * Type guard to check if an error is a RestError
 * @param error - The error to check
 * @returns True if the error is a RestError, false otherwise
 */
function isRestError(error: unknown): error is RestError;

Usage Examples:

import { isRestError } from "@azure/core-rest-pipeline";

// Generic error handling with type safety
async function makeRequest() {
  try {
    const response = await pipeline.sendRequest(client, request);
    return response;
  } catch (error) {
    if (isRestError(error)) {
      // TypeScript knows this is a RestError
      console.error(`HTTP Error ${error.statusCode}: ${error.message}`);
      
      if (error.statusCode === 429) {
        const retryAfter = error.response?.headers.get("Retry-After");
        console.log(`Rate limited. Retry after: ${retryAfter}`);
      }
      
      return null;
    } else {
      // Handle other error types
      console.error("Non-HTTP error:", error);
      throw error;
    }
  }
}

// Error filtering and logging
function logError(error: unknown) {
  if (isRestError(error)) {
    console.log({
      type: "RestError",
      message: error.message,
      statusCode: error.statusCode,
      code: error.code,
      url: error.request?.url,
      method: error.request?.method
    });
  } else if (error instanceof Error) {
    console.log({
      type: "Error",
      message: error.message,
      stack: error.stack
    });
  } else {
    console.log({
      type: "Unknown",
      error: String(error)
    });
  }
}

Error Code Constants

Standard error codes provided by RestError for common failure scenarios.

/**
 * Standard error codes for common failure scenarios
 */
interface RestErrorConstructor {
  /**
   * Something went wrong when making the request.
   * This means the actual request failed for some reason,
   * such as a DNS issue or the connection being lost.
   */
  readonly REQUEST_SEND_ERROR: string;

  /**
   * This means that parsing the response from the server failed.
   * It may have been malformed.
   */
  readonly PARSE_ERROR: string;
}

Usage Examples:

import { RestError, isRestError } from "@azure/core-rest-pipeline";

// Handle specific error types
async function robustRequest() {
  try {
    return await pipeline.sendRequest(client, request);
  } catch (error) {
    if (isRestError(error)) {
      switch (error.code) {
        case RestError.REQUEST_SEND_ERROR:
          console.error("Network or connectivity issue:", error.message);
          // Maybe retry with exponential backoff
          break;
          
        case RestError.PARSE_ERROR:
          console.error("Response parsing failed:", error.message);
          // Log the raw response for debugging
          console.error("Raw response:", error.response?.bodyAsText);
          break;
          
        default:
          console.error("HTTP error:", error.statusCode, error.message);
          break;
      }
    }
    throw error;
  }
}

Error Handling Patterns

Status Code Based Handling

import { isRestError } from "@azure/core-rest-pipeline";

async function handleHttpErrors() {
  try {
    const response = await pipeline.sendRequest(client, request);
    return response;
  } catch (error) {
    if (isRestError(error)) {
      switch (error.statusCode) {
        case 400:
          throw new Error("Bad Request: Check your request parameters");
        case 401:
          throw new Error("Unauthorized: Check your authentication credentials");
        case 403:
          throw new Error("Forbidden: You don't have permission for this resource");
        case 404:
          throw new Error("Not Found: The requested resource doesn't exist");
        case 429:
          const retryAfter = error.response?.headers.get("Retry-After");
          throw new Error(`Rate Limited: Retry after ${retryAfter} seconds`);
        case 500:
          throw new Error("Server Error: The service is experiencing issues");
        default:
          throw new Error(`HTTP ${error.statusCode}: ${error.message}`);
      }
    }
    throw error;
  }
}

Retry Decision Based on Errors

import { isRestError, RestError } from "@azure/core-rest-pipeline";

function shouldRetry(error: unknown, attempt: number, maxRetries: number): boolean {
  if (attempt >= maxRetries) return false;
  
  if (isRestError(error)) {
    // Retry network errors
    if (error.code === RestError.REQUEST_SEND_ERROR) {
      return true;
    }
    
    // Retry specific HTTP status codes
    if (error.statusCode && [429, 502, 503, 504].includes(error.statusCode)) {
      return true;
    }
    
    // Don't retry client errors (4xx except 429)
    if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429) {
      return false;
    }
  }
  
  return false;
}

async function requestWithRetry(maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
    try {
      return await pipeline.sendRequest(client, request);
    } catch (error) {
      if (!shouldRetry(error, attempt, maxRetries)) {
        throw error;
      }
      
      const delay = Math.min(1000 * Math.pow(2, attempt - 1), 30000);
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Error Context Extraction

import { isRestError } from "@azure/core-rest-pipeline";

interface ErrorContext {
  message: string;
  statusCode?: number;
  errorCode?: string;
  requestId?: string;
  url?: string;
  method?: string;
  timestamp: Date;
}

function extractErrorContext(error: unknown): ErrorContext {
  const context: ErrorContext = {
    message: error instanceof Error ? error.message : String(error),
    timestamp: new Date()
  };
  
  if (isRestError(error)) {
    context.statusCode = error.statusCode;
    context.errorCode = error.code;
    context.url = error.request?.url;
    context.method = error.request?.method;
    context.requestId = error.request?.requestId;
  }
  
  return context;
}

// Usage in error handling
try {
  await pipeline.sendRequest(client, request);
} catch (error) {
  const errorContext = extractErrorContext(error);
  console.error("Request failed:", errorContext);
  
  // Send to monitoring service
  // monitoring.recordError(errorContext);
}