CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sitemap

Sitemap-generating library and CLI tool for creating XML sitemaps that comply with the sitemaps.org protocol

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error classes and handling mechanisms for validation, configuration, and data format issues. The sitemap library provides detailed error reporting to help identify and resolve issues with sitemap data.

Capabilities

Error Levels and Handlers

Control how validation errors are handled throughout the library.

/**
 * How to handle errors in passed in urls
 */
enum ErrorLevel {
  /** Validation will be skipped and nothing logged or thrown */
  SILENT = 'silent',
  /** If an invalid value is encountered, a console.warn will be called with details */
  WARN = 'warn',
  /** An Error will be thrown on encountering invalid data */
  THROW = 'throw'
}

/**
 * Custom error handler function type
 * @param error - The validation error that occurred
 * @param level - Error level that triggered the handler
 */
type ErrorHandler = (error: Error, level: ErrorLevel) => void;

Configuration and URL Errors

Errors related to missing or invalid configuration and URL data.

/**
 * Thrown when a sitemap item is missing a required URL
 */
class NoURLError extends Error {
  constructor(message?: string);
}

/**
 * Thrown when required configuration is missing
 */
class NoConfigError extends Error {
  constructor(message?: string);
}

/**
 * Thrown when target folder is not specified for file operations
 */
class UndefinedTargetFolder extends Error {
  constructor(message?: string);
}

Sitemap Data Validation Errors

Errors for invalid sitemap item properties and values.

/**
 * Thrown when change frequency value is invalid
 */
class ChangeFreqInvalidError extends Error {
  constructor(message?: string);
}

/**
 * Thrown when priority value is not between 0.0 and 1.0
 */
class PriorityInvalidError extends Error {
  constructor(message?: string);
}

/**
 * Thrown when an attribute has an invalid value
 */
class InvalidAttrValue extends Error {
  constructor(message?: string);
}

/**
 * Internal error for malformed attributes
 */
class InvalidAttr extends Error {
  constructor(message?: string);
}

Video Sitemap Errors

Specialized errors for video sitemap validation.

/**
 * Thrown when video format is invalid
 */
class InvalidVideoFormat extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video duration is invalid or missing
 */
class InvalidVideoDuration extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video description exceeds 2048 characters
 */
class InvalidVideoDescription extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video title exceeds maximum length
 */
class InvalidVideoTitle extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video rating is not between 0.0 and 5.0
 */
class InvalidVideoRating extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video view count is invalid
 */
class InvalidVideoViewCount extends Error {
  constructor(message?: string);
}

/**
 * Thrown when more than 32 video tags are provided
 */
class InvalidVideoTagCount extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video category exceeds 256 characters
 */
class InvalidVideoCategory extends Error {
  constructor(message?: string);
}

/**
 * Thrown when family_friendly value is invalid
 */
class InvalidVideoFamilyFriendly extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video restriction format is invalid
 */
class InvalidVideoRestriction extends Error {
  constructor(message?: string);
}

/**
 * Thrown when restriction relationship is not allow/deny
 */
class InvalidVideoRestrictionRelationship extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video price type is invalid
 */
class InvalidVideoPriceType extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video resolution is invalid
 */
class InvalidVideoResolution extends Error {
  constructor(message?: string);
}

/**
 * Thrown when video price currency is not ISO 4217 format
 */
class InvalidVideoPriceCurrency extends Error {
  constructor(message?: string);
}

News Sitemap Errors

Errors specific to news sitemap validation.

/**
 * Thrown when news format is invalid
 */
class InvalidNewsFormat extends Error {
  constructor(message?: string);
}

/**
 * Thrown when news access value is not Registration or Subscription
 */
class InvalidNewsAccessValue extends Error {
  constructor(message?: string);
}

Stream and XML Errors

Errors related to stream processing and XML validation.

/**
 * Thrown when a stream is empty when data is expected
 */
class EmptyStream extends Error {
  constructor(message?: string);
}

/**
 * Thrown when a sitemap is empty when data is expected
 */
class EmptySitemap extends Error {
  constructor(message?: string);
}

/**
 * Thrown when XMLLint is not available for validation
 */
class XMLLintUnavailable extends Error {
  constructor(message?: string);
}

Usage Examples

Custom Error Handling

import { 
  validateSMIOptions, 
  ErrorLevel, 
  ErrorHandler,
  PriorityInvalidError 
} from "sitemap";

// Collect validation errors instead of throwing
const validationErrors: Error[] = [];

const errorCollector: ErrorHandler = (error, level) => {
  validationErrors.push(error);
  console.warn(`Validation ${level}: ${error.message}`);
  
  // Only throw on critical errors
  if (level === ErrorLevel.THROW) {
    throw error;
  }
};

// Validate sitemap items with custom error handling
const items = [
  { url: '/page1', priority: 1.5 }, // Invalid priority > 1.0
  { url: '/page2', changefreq: 'sometimes' }, // Invalid changefreq
  { url: '/page3' } // Valid item
];

const validatedItems = items.map(item => {
  try {
    return validateSMIOptions(item, ErrorLevel.WARN, errorCollector);
  } catch (error) {
    console.error('Critical validation error:', error.message);
    return null;
  }
}).filter(Boolean);

console.log(`Processed ${items.length} items, ${validatedItems.length} valid, ${validationErrors.length} errors`);

Error Type Checking

import { 
  InvalidVideoFormat,
  InvalidVideoDuration,
  PriorityInvalidError 
} from "sitemap";

function handleSitemapError(error: Error) {
  if (error instanceof PriorityInvalidError) {
    console.log('Priority must be between 0.0 and 1.0');
    // Handle priority errors
  } else if (error instanceof InvalidVideoFormat) {
    console.log('Video format is not supported');
    // Handle video format errors  
  } else if (error instanceof InvalidVideoDuration) {
    console.log('Video duration must be a positive number');
    // Handle video duration errors
  } else {
    console.log('Unknown validation error:', error.message);
    // Handle other errors
  }
}

// Usage in validation pipeline
try {
  const validatedItem = validateSMIOptions(sitemapItem, ErrorLevel.THROW);
  processSitemapItem(validatedItem);
} catch (error) {
  handleSitemapError(error as Error);
}

Batch Processing with Error Recovery

import { 
  normalizeURL, 
  validateSMIOptions, 
  ErrorLevel,
  NoURLError,
  ChangeFreqInvalidError 
} from "sitemap";

interface ProcessingResult {
  successful: SitemapItem[];
  failed: Array<{ item: any; error: Error }>;
}

function processSitemapBatch(rawItems: any[], hostname: string): ProcessingResult {
  const successful: SitemapItem[] = [];
  const failed: Array<{ item: any; error: Error }> = [];
  
  for (const rawItem of rawItems) {
    try {
      // First normalize the URL
      const normalized = normalizeURL(rawItem, hostname);
      
      // Then validate the complete item
      const validated = validateSMIOptions(normalized, ErrorLevel.THROW);
      
      successful.push(validated);
    } catch (error) {
      const err = error as Error;
      
      // Log specific error types differently
      if (err instanceof NoURLError) {
        console.warn('Skipping item without URL:', rawItem);
      } else if (err instanceof ChangeFreqInvalidError) {
        console.warn('Invalid changefreq, using default:', rawItem);
        // Could attempt to fix and retry
      } else {
        console.error('Validation failed for item:', rawItem, err.message);
      }
      
      failed.push({ item: rawItem, error: err });
    }
  }
  
  return { successful, failed };
}

// Usage
const rawData = [
  { url: '/page1', changefreq: 'invalid' },
  { url: '/page2', priority: 'high' }, // Should be number
  { changefreq: 'daily' }, // Missing URL
  { url: '/page3', priority: 0.8 } // Valid
];

const result = processSitemapBatch(rawData, 'https://example.com');
console.log(`${result.successful.length} valid, ${result.failed.length} failed`);

Stream Error Handling

import { 
  SitemapStream, 
  ErrorLevel,
  EmptyStream,
  InvalidAttrValue 
} from "sitemap";

const sitemap = new SitemapStream({ 
  hostname: 'https://example.com',
  level: ErrorLevel.WARN,
  errorHandler: (error, level) => {
    if (error instanceof InvalidAttrValue) {
      console.warn('Invalid attribute value, skipping:', error.message);
      return; // Continue processing
    } else if (error instanceof EmptyStream) {
      console.error('Stream is empty, no sitemap generated');
      throw error; // Stop processing
    } else {
      console.log(`${level} error:`, error.message);
    }
  }
});

sitemap.on('error', (error) => {
  console.error('Stream error:', error.message);
  // Handle stream-level errors
});

// Write items with potential validation issues
sitemap.write({ url: '/page1', priority: 'invalid' }); // Will trigger error handler
sitemap.write({ url: '/page2' }); // Valid item
sitemap.end();

Install with Tessl CLI

npx tessl i tessl/npm-sitemap

docs

cli-interface.md

error-handling.md

index.md

simple-api.md

sitemap-index.md

sitemap-parsing.md

sitemap-streams.md

validation-utilities.md

xml-validation.md

tile.json