This tutorial demonstrates how to use Droid Exec to refactor error messages across hundreds of files simultaneously. The script intelligently finds all ResponseError instantiations and improves their messages to be more descriptive, actionable, and user-friendly.
ResponseError
is Factory’s internal error handling class used to throw HTTP-style errors with specific status codes. These error classes are used throughout the codebase to handle API errors.
How it works
The script:
Finds files : Searches for all .ts
and .tsx
files containing ResponseError classes
Filters smartly : Excludes node_modules
, .git
, dist
, build
, and .next
directories
Identifies errors : Locates all ResponseError instantiations (400, 401, 403, 404, etc.)
Improves messages : Makes them more descriptive and actionable
Adds context : Includes what went wrong and potential fixes
User-friendly language : Removes technical jargon
Preserves metadata : Keeps error codes and metadata intact
Get the script
#!/bin/bash
# Droid Error Message Improvement Script
# Automatically improves ResponseError messages across the codebase
#
# Usage: ./droid-improve-errors.sh [directory]
# Example: ./droid-improve-errors.sh apps
set -e
# Configuration
CONCURRENCY = ${ CONCURRENCY :- 5 }
DRY_RUN = ${ DRY_RUN :- false }
TARGET_DIR = " ${1 :- . } "
# Colors for output
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
RED = '\033[0;31m'
NC = '\033[0m'
# Temp files for tracking
TEMP_DIR = $( mktemp -d )
FILES_LIST = " $TEMP_DIR /files.txt"
ERRORS_FOUND = " $TEMP_DIR /errors_found.txt"
MODIFIED_COUNT = 0
PROCESSED_COUNT = 0
ERRORS_IMPROVED = 0
# Cleanup on exit
trap "rm -rf $TEMP_DIR " EXIT
# Function to process a single file
process_file () {
local filepath = " $1 "
local filename = $( basename " $filepath " )
# Check if file contains ResponseError instantiations
if ! grep -qE "new ResponseError[0-9]+|throw new ResponseError" " $filepath " 2> /dev/null ; then
return 0
fi
# Count error instances for reporting
local error_count = $( grep -cE "new ResponseError[0-9]+" " $filepath " 2> /dev/null || echo 0 )
echo -e "${ BLUE }Processing: $filepath ${ NC }"
echo -e " Found $error_count error instantiation(s)"
# The AI prompt for improving error messages
local prompt = "Improve the error messages in $filepath :
Find all ResponseError instantiations (ResponseError400BadRequest, ResponseError401Unauthorized, etc.)
and improve their error messages following these guidelines:
1. Make messages more descriptive and actionable
2. Include context about what went wrong
3. Suggest potential fixes when appropriate
4. Use user-friendly language (avoid technical jargon)
5. Include relevant details without exposing sensitive data
Examples of improvements:
- 'Invalid api key format' → 'API key must be a 32-character alphanumeric string starting with \" fac\_ \" '
- 'Organization not found' → 'Organization with ID {orgId} not found. Please verify the organization exists and you have access.'
- 'Invalid CSRF token' → 'Security validation failed. Please refresh the page and try again.'
- 'Invalid request parameters' → 'Missing required field \" email \" . Please provide a valid email address.'
- 'User is already a member' → 'This user is already a member of the organization and cannot be invited again.'
Only modify the error message strings, preserve all other code including metadata parameters.
Return the complete file with improved error messages."
if [ " $DRY_RUN " = "true" ]; then
echo -e "${ YELLOW } [DRY RUN] Would improve $error_count error message(s)${ NC }"
echo " $error_count " >> " $ERRORS_FOUND "
return 0
fi
# Get original file hash for comparison
local original_hash = $( md5sum " $filepath " 2> /dev/null | cut -d ' ' -f1 || md5 -q " $filepath " )
# Run droid to improve error messages
if droid exec --auto low " $prompt " 2> /dev/null ; then
# Check if file was modified
local new_hash = $( md5sum " $filepath " 2> /dev/null | cut -d ' ' -f1 || md5 -q " $filepath " )
if [ " $original_hash " != " $new_hash " ]; then
echo -e "${ GREEN } ✓ Improved error messages${ NC }"
(( MODIFIED_COUNT ++ ))
(( ERRORS_IMPROVED += error_count ))
else
echo -e " No changes needed"
fi
(( PROCESSED_COUNT ++ ))
else
echo -e "${ RED } ✗ Failed to process${ NC }"
fi
}
# Export function and variables for parallel execution
export -f process_file
export DRY_RUN GREEN YELLOW BLUE RED NC ERRORS_FOUND
# Main execution
echo -e "${ BLUE }=== Droid Error Message Improvement ===${ NC }"
echo -e "${ BLUE }Directory: $TARGET_DIR ${ NC }"
echo -e "${ BLUE }Concurrency: $CONCURRENCY ${ NC }"
[ " $DRY_RUN " = "true" ] && echo -e "${ YELLOW }DRY RUN MODE${ NC }"
echo ""
# Find TypeScript files containing ResponseError
find " $TARGET_DIR " -type f \( -name "*.ts" -o -name "*.tsx" \) \
! -path "*/node_modules/*" \
! -path "*/.git/*" \
! -path "*/dist/*" \
! -path "*/build/*" \
! -path "*/.next/*" \
! -path "*/coverage/*" \
-exec grep -l "ResponseError[0-9]" {} \; 2> /dev/null > " $FILES_LIST " || true
FILE_COUNT = $( wc -l < " $FILES_LIST " | tr -d ' ' )
if [ " $FILE_COUNT " -eq 0 ]; then
echo -e "${ YELLOW }No files with ResponseError found${ NC }"
exit 0
fi
echo -e "${ BLUE }Found $FILE_COUNT files with ResponseError classes${ NC }\n"
# Process files in parallel
cat " $FILES_LIST " | xargs -n 1 -P " $CONCURRENCY " -I {} bash -c 'process_file "$@"' _ {}
# Calculate total errors found in dry run
if [ " $DRY_RUN " = "true" ] && [ -f " $ERRORS_FOUND " ]; then
TOTAL_ERRORS = $( awk '{sum+=$1} END {print sum}' " $ERRORS_FOUND " 2> /dev/null || echo 0 )
fi
# Show summary
echo -e "\n${ BLUE }=== Summary ===${ NC }"
echo -e "${ GREEN }Files scanned: $FILE_COUNT ${ NC }"
echo -e "${ GREEN }Files processed: $PROCESSED_COUNT ${ NC }"
if [ " $DRY_RUN " = "true" ]; then
[ -n " $TOTAL_ERRORS " ] && echo -e "${ YELLOW }Error messages to improve: $TOTAL_ERRORS ${ NC }"
else
echo -e "${ GREEN }Files modified: $MODIFIED_COUNT ${ NC }"
[ " $ERRORS_IMPROVED " -gt 0 ] && echo -e "${ GREEN }Error messages improved: ~ $ERRORS_IMPROVED ${ NC }"
fi
if [ " $DRY_RUN " = "false" ] && [ " $MODIFIED_COUNT " -gt 0 ]; then
echo -e "\n${ BLUE }Next steps:${ NC }"
echo " git diff # Review changes"
echo " npm run typecheck # Verify types"
echo " npm run test # Run tests"
echo " git add -A # Stage changes"
echo " git commit -m 'refactor: improve error messages for better UX'"
fi
Prerequisites
Before you begin, complete the Droid Exec installation .
Basic usage
Preview changes (dry run)
Always start with a dry run to see how many error messages need improvement before modifying files.
The dry run feature shows you exactly which files contain ResponseError instantiations and how many:
# Preview what would happen (no changes made)
DRY_RUN = true ./droid-improve-errors.sh apps/factory-admin/src/app/api/_utils/middleware.ts
# Example output:
# === Droid Error Message Improvement ===
# Directory: apps/factory-admin/src/app/api/_utils/middleware.ts
# Concurrency: 5
# DRY RUN MODE
#
# Found 1 files with ResponseError classes
#
# Processing: apps/factory-admin/src/app/api/_utils/middleware.ts
# Found 6 error instantiation(s)
# [DRY RUN] Would improve 6 error message(s)
#
# === Summary ===
# Files scanned: 1
# Files processed: 0
# Error messages to improve: 6
How dry run works:
When DRY_RUN=true
: Counts all ResponseError instantiations without making changes
When DRY_RUN=false
(default): Actually improves the error messages using AI
This helps you:
Estimate the scope of changes needed
Test on a small directory first
Plan your refactoring strategy
Apply refactoring
Once you’re ready, run the actual error message improvement:
# Actually improve the error messages (default behavior)
./droid-improve-errors.sh apps/factory-admin
# Or explicitly set DRY_RUN=false
DRY_RUN = false ./droid-improve-errors.sh apps/factory-admin
# Adjust concurrency for faster processing
CONCURRENCY = 10 ./droid-improve-errors.sh packages
Actual execution example:
% ./scripts/droid-improve-errors.sh apps/factory-admin/src/app/api/_utils/middleware.ts
=== Droid Error Message Improvement ===
Directory: apps/factory-admin/src/app/api/_utils/middleware.ts
Concurrency: 5
Found 1 files with ResponseError classes
Processing: apps/factory-admin/src/app/api/_utils/middleware.ts
Found 6 error instantiation ( s )
## Summary
I 've successfully improved all error messages in the `apps/factory-admin/src/app/api/_utils/middleware.ts` file. The improvements include making the messages more descriptive, actionable, and user-friendly while providing helpful context and suggestions for resolution. All 7 error instantiations were updated, and the TypeScript compilation verified that the changes are syntactically correct.
Example 1: Session Authentication
// middleware.ts
if ( ! sessionCookie ?. value ) {
throw new ResponseError401Unauthorized ( 'No session' );
}
if ( ! userRecord ) {
throw new ResponseError401Unauthorized ( 'Invalid session' );
}
Example 2: Bearer Token Authorization
// middleware.ts
if ( ! authHeader ) {
throw new ResponseError401Unauthorized ( 'Missing auth header' );
}
if ( authHeader !== `Bearer ${ secret } ` ) {
throw new ResponseError401Unauthorized ( 'Invalid token' );
}
Best practices
Follow these best practices for safe and effective error message improvement.
Start with a dry run
Always preview the scope of changes first: # See how many errors need improvement
DRY_RUN = true ./droid-improve-errors.sh packages
Process incrementally
For large codebases, tackle one module at a time: # Process each app separately for easier review
./droid-improve-errors.sh apps/factory-admin
git add -A && git commit -m "refactor(factory-admin): improve error messages"
./droid-improve-errors.sh apps/factory-app
git add -A && git commit -m "refactor(factory-app): improve error messages"