277 lines
7.6 KiB
Markdown
277 lines
7.6 KiB
Markdown
# 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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|