or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

caching-errors.mdindex.mdprotocols.md
tile.json

caching-errors.mddocs/

Caching and Error Handling

Comprehensive caching system and error handling for efficient resource management and robust error reporting.

Capabilities

Cache Validation

All protocol handlers support cache validation to avoid redundant requests when resources haven't changed.

Cache Validation Process:

  1. Data URIs: Uses SHA1 hash comparison of the URI content
  2. File URIs: Compares file modification time (mtime) from filesystem stats
  3. FTP URIs: Compares last modified date from FTP server metadata
  4. HTTP/HTTPS URIs: Uses standard HTTP cache headers (If-Modified-Since, If-None-Match, Cache-Control, Expires)

Usage Pattern:

import { getUri } from "get-uri";

// First request - fetches for real
const stream = await getUri('https://api.example.com/data.json');

try {
  // Subsequent request with cache validation
  const newStream = await getUri('https://api.example.com/data.json', {
    cache: stream
  });
} catch (err) {
  if (err.code === 'ENOTMODIFIED') {
    // Resource unchanged, reuse previous stream
    console.log('Using cached data');
    // Continue using original stream
  } else {
    throw err; // Different error
  }
}

Error Classes

Standardized error handling across all protocols with specific error codes.

NotFoundError

Thrown when a resource does not exist at the specified URI.

/**
 * Error thrown when resource is not found at the specified endpoint
 */
class NotFoundError extends Error {
  /** Error code for not found resources */
  code: 'ENOTFOUND';
  
  /**
   * @param message - Optional custom error message
   * @default "File does not exist at the specified endpoint"
   */
  constructor(message?: string);
}

Common Scenarios:

  • File URIs: File doesn't exist in filesystem
  • HTTP/HTTPS URIs: 404 status code responses
  • FTP URIs: File not found on FTP server (550 error code)

Usage Example:

import { getUri } from "get-uri";

try {
  const stream = await getUri('file:///nonexistent/file.txt');
} catch (err) {
  if (err.code === 'ENOTFOUND') {
    console.log('File not found:', err.message);
    // Handle missing resource
  }
}

NotModifiedError

Thrown when cache validation indicates the resource hasn't changed since the previous request.

/**
 * Error thrown when resource has not been modified since the provided cache
 */
class NotModifiedError extends Error {
  /** Error code for unmodified resources */
  code: 'ENOTMODIFIED';
  
  /**
   * @param message - Optional custom error message  
   * @default "Source has not been modified since the provided \"cache\", re-use previous results"
   */
  constructor(message?: string);
}

Usage Example:

import { getUri } from "get-uri";

const originalStream = await getUri('https://api.example.com/data.json');

try {
  const newStream = await getUri('https://api.example.com/data.json', {
    cache: originalStream
  });
} catch (err) {
  if (err.code === 'ENOTMODIFIED') {
    // Resource unchanged, use original stream
    return originalStream;
  }
  throw err;
}

HTTPError

Thrown for HTTP-level errors beyond standard not found cases.

/**
 * Error thrown for HTTP application errors
 */
class HTTPError extends Error {
  /** Formatted error code based on status message */
  code: string;
  /** HTTP status code */
  statusCode: number;
  
  /**
   * @param statusCode - HTTP status code
   * @param message - Optional message (defaults to HTTP status text)
   */
  constructor(statusCode: number, message?: string);
}

Usage Example:

import { getUri } from "get-uri";

try {
  const stream = await getUri('https://api.example.com/protected');
} catch (err) {
  if (err instanceof HTTPError) {
    console.log(`HTTP Error ${err.statusCode}: ${err.message}`);
    
    if (err.statusCode === 401) {
      // Handle authentication error
    } else if (err.statusCode === 403) {
      // Handle authorization error  
    }
  }
}

HTTP Cache Headers

The HTTP protocol handler supports standard HTTP caching mechanisms.

Cache-Control Support

// Supported Cache-Control directives:
// - max-age: Sets expiration time relative to response date
// - must-revalidate: Forces revalidation (currently not implemented)
// - no-cache: Forces fresh request, ignores cache
// - no-store: Forces fresh request, ignores cache

const stream = await getUri('https://api.example.com/data', {
  headers: {
    'Cache-Control': 'max-age=3600' // Cache for 1 hour
  }
});

Conditional Requests

When a cache is provided, appropriate conditional request headers are automatically added:

// Automatically adds headers when cache is present:
// - If-Modified-Since: Uses Last-Modified from cache
// - If-None-Match: Uses ETag from cache

const cachedStream = await getUri('https://api.example.com/data', {
  cache: previousStream // Adds conditional headers automatically
});

Error Handling Best Practices

import { getUri } from "get-uri";

async function fetchResource(uri: string, cache?: any) {
  try {
    return await getUri(uri, { cache });
  } catch (err) {
    switch (err.code) {
      case 'ENOTFOUND':
        console.log('Resource not found:', uri);
        return null;
        
      case 'ENOTMODIFIED':
        console.log('Resource unchanged, using cache');
        return cache;
        
      default:
        // Check for HTTP errors by status code property
        if (err.statusCode) {
          console.log(`HTTP ${err.statusCode}: ${err.message}`);
          // Handle specific HTTP errors
        }
        throw err; // Re-throw unexpected errors
    }
  }
}