Files
sales-data-analysis/.cursor/rules/error_handling.md
Jonathan Pressnell cf0b596449 Initial commit: sales analysis template
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-06 09:16:34 -05:00

7.6 KiB

Error Handling Best Practices

This guide defines how to handle errors in a way that's helpful for both users and AI assistants.

Error Message Structure

Required Elements

Every error message should include:

  1. What went wrong - Specific error description
  2. Where it occurred - File/function context
  3. Why it happened - Root cause explanation
  4. How to fix - Actionable steps
  5. Reference - Link to relevant documentation

Template

raise ErrorType(
    f"[What] - [Specific description]\n"
    f"\n"
    f"Context: [Where/When this occurred]\n"
    f"Reason: [Why this happened]\n"
    f"\n"
    f"Solution:\n"
    f"1. [Step 1]\n"
    f"2. [Step 2]\n"
    f"\n"
    f"For more help, see: [Documentation reference]"
)

Common Error Patterns

Data Loading Errors

# Good: Comprehensive error message
if REVENUE_COLUMN not in df.columns:
    available_cols = list(df.columns)[:10]  # Show first 10
    raise ValueError(
        f"Required column '{REVENUE_COLUMN}' not found in data.\n"
        f"\n"
        f"Context: Loading data from {filepath}\n"
        f"Available columns: {available_cols}\n"
        f"\n"
        f"Solution:\n"
        f"1. Check your CSV file column names\n"
        f"2. Update REVENUE_COLUMN in config.py to match your data\n"
        f"3. Run: python config_validator.py to validate configuration\n"
        f"\n"
        f"For more help, see: .cursor/rules/data_loading.md"
    )

# Bad: Vague error
if REVENUE_COLUMN not in df.columns:
    raise ValueError("Column not found")

Configuration Errors

# Good: Actionable error
if LTM_ENABLED and (LTM_START is None or LTM_END is None):
    raise ValueError(
        f"LTM configuration error: LTM_ENABLED is True but LTM period is not set.\n"
        f"\n"
        f"Context: Configuration in config.py\n"
        f"Current values: LTM_ENABLED={LTM_ENABLED}, LTM_START={LTM_START}, LTM_END={LTM_END}\n"
        f"\n"
        f"Solution:\n"
        f"1. Set LTM_START_MONTH, LTM_START_YEAR, LTM_END_MONTH, LTM_END_YEAR in config.py\n"
        f"2. Or set LTM_ENABLED = False if you don't need LTM\n"
        f"3. Run: python config_validator.py to check configuration\n"
        f"\n"
        f"For more help, see: .cursor/rules/ltm_methodology.md"
    )

Data Quality Errors

# Good: Helpful data quality error
if date_coverage < 0.5:  # Less than 50% coverage
    raise ValueError(
        f"Data quality issue: Only {date_coverage:.1%} of rows have valid dates.\n"
        f"\n"
        f"Context: Date parsing in data_loader.py\n"
        f"Rows with dates: {date_count:,} / {total_rows:,}\n"
        f"\n"
        f"Solution:\n"
        f"1. Check date format in your CSV file\n"
        f"2. Add fallback date columns to DATE_FALLBACK_COLUMNS in config.py\n"
        f"3. Ensure at least one date column (Month, Year) exists\n"
        f"4. Run: python data_quality.py to analyze data quality\n"
        f"\n"
        f"For more help, see: .cursor/rules/data_loading.md"
    )

Error Handling Patterns

Try-Except with Context

# Good: Provides context and recovery options
try:
    df = load_sales_data(get_data_path())
except FileNotFoundError as e:
    error_msg = (
        f"Data file not found: {e}\n"
        f"\n"
        f"Context: Attempting to load data for analysis\n"
        f"Expected file: {get_data_path()}\n"
        f"\n"
        f"Solution:\n"
        f"1. Check that your CSV file exists at the expected location\n"
        f"2. Update DATA_FILE in config.py with correct filename\n"
        f"3. Or update DATA_DIR if file is in a subdirectory\n"
        f"4. Run: python setup_wizard.py to reconfigure\n"
        f"\n"
        f"For more help, see: .cursor/rules/common_errors.md"
    )
    raise FileNotFoundError(error_msg) from e

Validation with Helpful Messages

# Good: Validates and provides specific guidance
def validate_data_structure(df: pd.DataFrame) -> Tuple[bool, str]:
    """
    Validate DataFrame has required structure
    
    Returns:
        Tuple[bool, str]: (is_valid, error_message)
                         If is_valid is False, error_message contains actionable guidance
    """
    errors = []
    
    if REVENUE_COLUMN not in df.columns:
        errors.append(
            f"Missing required column '{REVENUE_COLUMN}'. "
            f"Update REVENUE_COLUMN in config.py to match your data."
        )
    
    if DATE_COLUMN not in df.columns:
        errors.append(
            f"Missing required column '{DATE_COLUMN}'. "
            f"Update DATE_COLUMN in config.py or add fallback columns."
        )
    
    if len(df) == 0:
        errors.append(
            f"DataFrame is empty. Check date filters (MIN_YEAR, MAX_DATE) in config.py."
        )
    
    if errors:
        error_msg = "Data validation failed:\n" + "\n".join(f"  - {e}" for e in errors)
        error_msg += "\n\nRun: python config_validator.py for detailed validation"
        return False, error_msg
    
    return True, "OK"

Warning Messages

When to Use Warnings

Use warnings (not errors) for:

  • Non-critical data quality issues
  • Optional features that aren't configured
  • Deprecated functionality
  • Performance considerations

Warning Format

import warnings

# Good: Informative warning
if date_coverage < 0.9:  # Less than 90% but not critical
    warnings.warn(
        f"Date coverage is {date_coverage:.1%} ({missing_count:,} rows missing dates).\n"
        f"Consider adding fallback date columns to improve coverage.\n"
        f"See .cursor/rules/data_loading.md for details.",
        UserWarning
    )

Logging Errors

Use Structured Logging

from logger_config import get_logger

logger = get_logger('analysis_name')

try:
    df = load_sales_data(get_data_path())
except Exception as e:
    logger.error(
        f"Failed to load data: {e}",
        exc_info=True,  # Include stack trace
        extra={
            'file_path': str(get_data_path()),
            'config_file': 'config.py',
            'suggestion': 'Run config_validator.py to check configuration'
        }
    )
    raise

AI-Friendly Error Messages

Help AI Understand and Fix

Error messages should help AI assistants:

  1. Understand what went wrong
  2. Know where to look for fixes
  3. Suggest specific solutions
  4. Reference relevant documentation
# Good: AI can parse and act on this
if column not in df.columns:
    raise ValueError(
        f"Column '{column}' not found.\n"
        f"Available: {list(df.columns)}\n"
        f"Fix: Update {column}_COLUMN in config.py\n"
        f"See: .cursor/rules/data_loading.md"
    )

# Bad: AI has no context
if column not in df.columns:
    raise ValueError("Not found")

Error Recovery

Provide Recovery Options

# Good: Offers recovery path
def load_sales_data(filepath=None):
    try:
        df = pd.read_csv(filepath)
    except FileNotFoundError:
        # Suggest alternatives
        suggestions = [
            f"1. Check file path: {filepath}",
            f"2. Update DATA_FILE in config.py",
            f"3. Run: python setup_wizard.py",
            f"4. Generate sample data: python generate_sample_data.py"
        ]
        raise FileNotFoundError(
            f"Data file not found: {filepath}\n"
            f"\n"
            f"Options:\n" + "\n".join(suggestions)
        )

Summary

Good error handling:

  • Specific and actionable
  • Provides context
  • Suggests solutions
  • References documentation
  • Helps both users and AI assistants

Last Updated: January 2026
For: Error handling in sales_analysis_template