or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdconfiguration.mdcore-parsing.mderror-handling.mdindex.mdstream-processing.mdtransformation-hooks.md
tile.json

error-handling.mddocs/

Error Handling

Custom error handling system with specific error types for parsing issues, validation failures, and comprehensive error information for debugging CSV parsing problems.

Capabilities

CSVError Class

Custom error class extending native Error with CSV-specific error information and context.

/**
 * Custom error class for CSV parsing errors
 * @extends Error
 */
class CSVError extends Error {
  /** Error message describing the issue */
  err: string;
  
  /** Line number where error occurred (zero-based) */
  line: number;
  
  /** Additional context information about the error */
  extra?: string;
  
  /**
   * Creates a new CSV parsing error
   * @param err - Error message
   * @param line - Line number where error occurred
   * @param extra - Optional additional error context
   */
  constructor(err: string, line: number, extra?: string);
  
  /**
   * Convert error to JSON for serialization
   * @returns Object with error details
   */
  toJSON(): {err: string, line: number, extra?: string};
}

Usage Examples:

import csvtojson from "csvtojson";

try {
  const jsonArray = await csvtojson({
    checkColumn: true,
    maxRowLength: 1000
  })
  .fromString('name,age,city\nAlice,25\nBob,30,London,Extra');
} catch (error) {
  if (error instanceof CSVError) {
    console.log('CSV Error:', error.err);
    console.log('Line:', error.line);
    if (error.extra) {
      console.log('Context:', error.extra);
    }
    
    // Serialize error
    const errorData = error.toJSON();
    console.log('Error data:', errorData);
  }
}

Static Error Factories

Predefined static methods for creating specific types of CSV errors.

/**
 * Create error for column count mismatch
 * @param index - Line index where mismatch occurred
 * @param extra - Optional additional context
 * @returns CSVError instance
 */
static column_mismatched(index: number, extra?: string): CSVError;

/**
 * Create error for unclosed quote
 * @param index - Line index where unclosed quote occurred  
 * @param extra - Optional additional context
 * @returns CSVError instance
 */
static unclosed_quote(index: number, extra?: string): CSVError;

/**
 * Create CSVError from JSON object (for deserialization)
 * @param obj - Object with err, line, and optional extra properties
 * @returns CSVError instance
 */
static fromJSON(obj: {err: string, line: number, extra?: string}): CSVError;

Usage Examples:

import csvtojson, { CSVError } from "csvtojson";

// Handle different error types
csvtojson({
  checkColumn: true,
  quote: '"'
})
.fromFile('./problematic-data.csv')
.subscribe(
  (jsonObj) => {
    console.log('Parsed:', jsonObj);
  },
  (error) => {
    if (error instanceof CSVError) {
      switch (error.err) {
        case 'column_mismatched':
          console.error(`Column count mismatch at line ${error.line + 1}`);
          if (error.extra) {
            console.error(`Expected columns but got: ${error.extra}`);
          }
          break;
          
        case 'unclosed_quote':
          console.error(`Unclosed quote at line ${error.line + 1}`);
          if (error.extra) {
            console.error(`Near: ${error.extra}`);
          }
          break;
          
        default:
          console.error(`Parsing error: ${error.err} at line ${error.line + 1}`);
      }
    }
  }
);

Error Context and Debugging

Comprehensive error information for debugging complex parsing issues.

interface CSVError extends Error {
  /** The specific error type identifier */
  err: 'column_mismatched' | 'unclosed_quote' | 'row_exceed' | string;
  
  /** Zero-based line number where error occurred */
  line: number;
  
  /** Additional context like partial data or expected vs actual values */
  extra?: string;
}

Usage Examples:

import csvtojson from "csvtojson";

async function parseWithDetailedErrorHandling(filePath: string) {
  try {
    const result = await csvtojson({
      checkColumn: true,
      maxRowLength: 10000,
      quote: '"'
    })
    .fromFile(filePath);
    
    return result;
  } catch (error) {
    if (error instanceof CSVError) {
      // Create detailed error report
      const errorReport = {
        type: error.err,
        lineNumber: error.line + 1, // Convert to 1-based
        message: error.message,
        context: error.extra,
        file: filePath,
        timestamp: new Date().toISOString()
      };
      
      // Log structured error
      console.error('CSV Parsing Error:', JSON.stringify(errorReport, null, 2));
      
      // Handle specific error types
      switch (error.err) {
        case 'column_mismatched':
          console.error('Suggestion: Check if delimiters are consistent');
          break;
        case 'unclosed_quote':
          console.error('Suggestion: Check for unescaped quotes in data');
          break;
        case 'row_exceed':
          console.error('Suggestion: Increase maxRowLength or check for corrupted data');
          break;
      }
      
      throw errorReport;
    }
    
    // Re-throw non-CSV errors
    throw error;
  }
}

Error Recovery Strategies

Strategies for handling and recovering from parsing errors in production.

/**
 * Error handling patterns for robust CSV processing
 */
interface ErrorRecoveryOptions {
  /** Continue processing after errors */
  continueOnError?: boolean;
  /** Maximum errors before aborting */
  maxErrors?: number;
  /** Callback for handling individual errors */
  onError?: (error: CSVError) => boolean; // Return true to continue
}

Usage Examples:

import csvtojson, { CSVError } from "csvtojson";

// Graceful error handling with recovery
async function robustCSVParsing(filePath: string) {
  const results: any[] = [];
  const errors: CSVError[] = [];
  let errorCount = 0;
  const maxErrors = 10;
  
  return new Promise((resolve, reject) => {
    csvtojson({
      checkColumn: false, // More lenient parsing
      ignoreEmpty: true,  // Skip empty rows
      maxRowLength: 100000
    })
    .fromFile(filePath)
    .subscribe(
      (jsonObj, lineNumber) => {
        try {
          // Validate data before adding
          if (isValidRecord(jsonObj)) {
            results.push(jsonObj);
          } else {
            console.warn(`Invalid record at line ${lineNumber}:`, jsonObj);
          }
        } catch (validationError) {
          console.error(`Validation error at line ${lineNumber}:`, validationError);
        }
      },
      (csvError) => {
        errorCount++;
        errors.push(csvError);
        
        console.error(`Error ${errorCount}/${maxErrors} at line ${csvError.line + 1}: ${csvError.err}`);
        
        if (errorCount >= maxErrors) {
          reject(new Error(`Too many errors (${errorCount}). Aborting.`));
        }
      },
      () => {
        // Parsing completed
        console.log(`Parsing completed with ${results.length} records and ${errorCount} errors`);
        resolve({
          data: results,
          errors: errors,
          stats: {
            totalRecords: results.length,
            errorCount: errorCount,
            successRate: (results.length / (results.length + errorCount)) * 100
          }
        });
      }
    );
  });
}

function isValidRecord(record: any): boolean {
  // Implement your validation logic
  return record && typeof record === 'object' && Object.keys(record).length > 0;
}

Stream Error Handling

Handle errors in streaming scenarios with proper cleanup and resource management.

/**
 * Stream-specific error handling for large file processing
 */
interface StreamErrorHandling {
  /** Handle stream errors without stopping processing */
  onStreamError?: (error: Error) => void;
  /** Handle individual record errors */
  onRecordError?: (error: CSVError, record: any) => boolean;
}

Usage Examples:

import csvtojson from "csvtojson";
import { createWriteStream } from "fs";

// Streaming with error handling and logging
function processLargeCSVWithErrorLogging(inputFile: string, outputFile: string) {
  const outputStream = createWriteStream(outputFile);
  const errorLogStream = createWriteStream(`${outputFile}.errors.log`);
  
  let processedCount = 0;
  let errorCount = 0;
  
  csvtojson({
    checkType: true,
    trim: true
  })
  .fromFile(inputFile)
  .subscribe(
    async (jsonObj, lineNumber) => {
      try {
        // Process and validate data
        const processedObj = await processRecord(jsonObj);
        
        // Write to output
        outputStream.write(JSON.stringify(processedObj) + '\n');
        processedCount++;
        
        if (processedCount % 1000 === 0) {
          console.log(`Processed ${processedCount} records`);
        }
      } catch (processingError) {
        errorCount++;
        const errorEntry = {
          line: lineNumber + 1,
          error: processingError.message,
          data: jsonObj,
          timestamp: new Date().toISOString()
        };
        
        errorLogStream.write(JSON.stringify(errorEntry) + '\n');
      }
    },
    (csvError) => {
      // Handle CSV parsing errors
      errorCount++;
      const errorEntry = {
        line: csvError.line + 1,
        type: 'csv_parse_error',
        error: csvError.err,
        extra: csvError.extra,
        timestamp: new Date().toISOString()
      };
      
      errorLogStream.write(JSON.stringify(errorEntry) + '\n');
      console.error(`CSV parsing error at line ${csvError.line + 1}: ${csvError.err}`);
    },
    () => {
      // Cleanup and final reporting
      outputStream.end();
      errorLogStream.end();
      
      console.log(`\nProcessing completed:`);
      console.log(`- Processed records: ${processedCount}`);
      console.log(`- Errors: ${errorCount}`);
      console.log(`- Success rate: ${((processedCount / (processedCount + errorCount)) * 100).toFixed(2)}%`);
    }
  );
}

async function processRecord(record: any): Promise<any> {
  // Implement your record processing logic
  // Throw errors for invalid records
  if (!record.email || !record.email.includes('@')) {
    throw new Error('Invalid email address');
  }
  
  return {
    ...record,
    processed_at: new Date().toISOString()
  };
}