- Add comprehensive documentation in botbook/ with 12 chapters - Add botapp/ Tauri desktop application - Add botdevice/ IoT device support - Add botlib/ shared library crate - Add botmodels/ Python ML models service - Add botplugin/ browser extension - Add botserver/ reorganized server code - Add bottemplates/ bot templates - Add bottest/ integration tests - Add botui/ web UI server - Add CI/CD workflows in .forgejo/workflows/ - Add AGENTS.md and PROD.md documentation - Add dependency management scripts (DEPENDENCIES.sh/ps1) - Remove legacy src/ structure and migrations - Clean up temporary and backup files
10 KiB
ON ERROR RESUME NEXT
The ON ERROR RESUME NEXT keyword enables BASIC error handling, allowing scripts to continue execution when errors occur instead of terminating immediately.
Syntax
ON ERROR RESUME NEXT ' Enable error trapping
ON ERROR GOTO 0 ' Disable error trapping
Description
ON ERROR RESUME NEXT enables error trapping mode where execution continues to the next statement after an error occurs, rather than halting the script. This pattern is borrowed from BASIC and provides a simple way to handle errors gracefully in BASIC scripts.
When error trapping is enabled:
- Errors are captured but don't stop execution
- The
ERRORfunction returnsTRUEif an error occurred - The
ERROR MESSAGEfunction returns the error description - The
ERRvariable contains the error number
Use ON ERROR GOTO 0 to disable error trapping and restore normal error behavior.
Error State Keywords
| Keyword | Description | Example |
|---|---|---|
ON ERROR RESUME NEXT |
Enable error trapping | ON ERROR RESUME NEXT |
ON ERROR GOTO 0 |
Disable error trapping | ON ERROR GOTO 0 |
ERROR |
Returns TRUE if error occurred | IF ERROR THEN |
ERROR MESSAGE |
Get last error message | msg = ERROR MESSAGE |
ERR |
Get error number | code = ERR |
CLEAR ERROR |
Clear error state | CLEAR ERROR |
THROW |
Raise a custom error | THROW "Invalid input" |
ASSERT |
Assert a condition | ASSERT count > 0, "Count must be positive" |
Examples
Basic Error Handling
' Enable error trapping
ON ERROR RESUME NEXT
' Attempt a risky operation
result = GET "https://api.example.com/data"
' Check if it failed
IF ERROR THEN
TALK "Sorry, I couldn't fetch the data: " + ERROR MESSAGE
ELSE
TALK "Data retrieved successfully!"
END IF
Multiple Operations with Error Checking
ON ERROR RESUME NEXT
' Try to read a file
content = READ "config.csv"
IF ERROR THEN
TALK "Config file not found, using defaults"
CLEAR ERROR
content = "name,value\ndefault,true"
END IF
' Try to parse it
data = PARSE_CSV(content)
IF ERROR THEN
TALK "Failed to parse config: " + ERROR MESSAGE
CLEAR ERROR
END IF
' Continue with whatever data we have
TALK "Loaded " + LEN(data) + " configuration entries"
Database Operations
ON ERROR RESUME NEXT
' Try to insert a record
INSERT "customers", #{
"name": customer_name,
"email": customer_email,
"created_at": NOW()
}
IF ERROR THEN
IF INSTR(ERROR MESSAGE, "duplicate") > 0 THEN
TALK "This customer already exists in our system."
ELSE IF INSTR(ERROR MESSAGE, "connection") > 0 THEN
TALK "Database is temporarily unavailable. Please try again."
ELSE
TALK "Could not save customer: " + ERROR MESSAGE
END IF
ELSE
TALK "Customer saved successfully!"
END IF
ON ERROR GOTO 0 ' Disable error trapping
HTTP Request with Fallback
ON ERROR RESUME NEXT
' Try primary API
data = GET "https://primary-api.example.com/endpoint"
IF ERROR THEN
PRINT "Primary API failed: " + ERROR MESSAGE
CLEAR ERROR
' Try fallback API
data = GET "https://fallback-api.example.com/endpoint"
IF ERROR THEN
TALK "Both APIs are unavailable. Please try again later."
RETURN
END IF
END IF
' Process the data
TALK "Retrieved: " + data.name
File Operations with Cleanup
ON ERROR RESUME NEXT
' Generate a report
report = GENERATE PDF "templates/report.html", report_data, "temp/report.pdf"
IF ERROR THEN
TALK "Failed to generate report: " + ERROR MESSAGE
CLEAR ERROR
ELSE
' Try to send it
SEND MAIL recipient, "Your Report", "Please find your report attached.", [report.localName]
IF ERROR THEN
TALK "Report generated but email failed: " + ERROR MESSAGE
DOWNLOAD report.url AS "report.pdf"
TALK "You can download it directly instead."
ELSE
TALK "Report sent successfully!"
END IF
' Clean up temp file
DELETE "temp/report.pdf"
' Ignore cleanup errors
CLEAR ERROR
END IF
ON ERROR GOTO 0
Validation with ASSERT
ON ERROR RESUME NEXT
' Validate input
ASSERT LEN(email) > 0, "Email is required"
IF ERROR THEN
TALK ERROR MESSAGE
RETURN
END IF
ASSERT INSTR(email, "@") > 0, "Invalid email format"
IF ERROR THEN
TALK ERROR MESSAGE
RETURN
END IF
ASSERT amount > 0, "Amount must be positive"
IF ERROR THEN
TALK ERROR MESSAGE
RETURN
END IF
' All validations passed
TALK "Processing your request..."
Custom Error with THROW
ON ERROR RESUME NEXT
' Check business rules
IF quantity > inventory_count THEN
THROW "Insufficient inventory: only " + inventory_count + " items available"
END IF
IF customer_credit < total_price THEN
THROW "Insufficient credit: need $" + FORMAT(total_price - customer_credit, "#,##0.00") + " more"
END IF
' Check for errors from THROW
IF ERROR THEN
TALK "Cannot process order: " + ERROR MESSAGE
RETURN
END IF
' Continue with order processing
TALK "Order confirmed!"
Loop with Error Recovery
ON ERROR RESUME NEXT
successful = 0
failed = 0
FOR EACH item IN items_to_process
' Process each item
result = POST "https://api.example.com/process", item
IF ERROR THEN
PRINT "Failed to process item " + item.id + ": " + ERROR MESSAGE
failed = failed + 1
CLEAR ERROR ' Clear error to continue loop
ELSE
successful = successful + 1
END IF
NEXT
ON ERROR GOTO 0
TALK "Processing complete: " + successful + " succeeded, " + failed + " failed"
Nested Error Handling
ON ERROR RESUME NEXT
' Outer operation
connection = CONNECT "database"
IF ERROR THEN
TALK "Database connection failed"
RETURN
END IF
' Inner operation
ON ERROR RESUME NEXT
result = QUERY connection, "SELECT * FROM users"
IF ERROR THEN
TALK "Query failed, trying alternative..."
CLEAR ERROR
result = QUERY connection, "SELECT * FROM users_backup"
END IF
IF ERROR THEN
TALK "All queries failed: " + ERROR MESSAGE
ELSE
TALK "Found " + LEN(result) + " users"
END IF
ON ERROR GOTO 0
Error Codes
Common error codes returned by ERR:
| Code | Category | Description |
|---|---|---|
| 1xxx | Network | HTTP and connection errors |
| 2xxx | Database | SQL and data errors |
| 3xxx | File | File system errors |
| 4xxx | Validation | Input validation errors |
| 5xxx | Auth | Authentication/authorization errors |
| 9xxx | System | Internal system errors |
Checking Error Codes
ON ERROR RESUME NEXT
result = GET url
IF ERROR THEN
SELECT CASE ERR
CASE 1001
TALK "Network timeout - please try again"
CASE 1002
TALK "Server not found"
CASE 1003
TALK "Connection refused"
CASE 1404
TALK "Resource not found"
CASE 1500
TALK "Server error - please try later"
CASE ELSE
TALK "Error " + ERR + ": " + ERROR MESSAGE
END SELECT
END IF
Best Practices
Always Clear Errors When Continuing
ON ERROR RESUME NEXT
result = RISKY_OPERATION()
IF ERROR THEN
' Handle the error
TALK "Operation failed"
CLEAR ERROR ' Clear before next operation
END IF
' Next operation won't see stale error
result2 = ANOTHER_OPERATION()
Disable Error Trapping When Done
ON ERROR RESUME NEXT
' Protected code section
result = RISKY_OPERATION()
IF ERROR THEN
TALK "Handled error: " + ERROR MESSAGE
END IF
ON ERROR GOTO 0 ' Re-enable normal error behavior
' Errors here will halt execution as normal
Log Errors for Debugging
ON ERROR RESUME NEXT
result = COMPLEX_OPERATION()
IF ERROR THEN
' Log full details for debugging
PRINT "ERROR at " + FORMAT(NOW(), "YYYY-MM-DD HH:mm:ss")
PRINT " Code: " + ERR
PRINT " Message: " + ERROR MESSAGE
PRINT " Context: processing " + current_item.id
' User-friendly message
TALK "Something went wrong. Our team has been notified."
CLEAR ERROR
END IF
Don't Ignore Errors Silently
' BAD - Errors are silently ignored
ON ERROR RESUME NEXT
data = GET url
TALK "Got data: " + data ' May fail if GET failed
' GOOD - Check and handle errors
ON ERROR RESUME NEXT
data = GET url
IF ERROR THEN
TALK "Could not fetch data"
data = DEFAULT_DATA
END IF
TALK "Got data: " + data
Use Specific Error Checks
ON ERROR RESUME NEXT
result = DATABASE_OPERATION()
IF ERROR THEN
error_msg = ERROR MESSAGE
' Handle specific errors differently
IF INSTR(error_msg, "timeout") > 0 THEN
WAIT 2
result = DATABASE_OPERATION() ' Retry
ELSE IF INSTR(error_msg, "duplicate") > 0 THEN
TALK "This record already exists"
ELSE IF INSTR(error_msg, "permission") > 0 THEN
TALK "You don't have permission for this action"
ELSE
TALK "Database error: " + error_msg
END IF
END IF
Comparison with TRY...CATCH
For more complex error handling, you can use structured TRY...CATCH blocks:
' ON ERROR style (simpler)
ON ERROR RESUME NEXT
result = RISKY()
IF ERROR THEN
TALK "Error: " + ERROR MESSAGE
END IF
ON ERROR GOTO 0
' TRY...CATCH style (more structured)
TRY
result = RISKY()
CATCH e
TALK "Error: " + e.message
END TRY
Use ON ERROR RESUME NEXT for:
- Simple scripts with few error points
- Quick prototyping
- BASIC-familiar developers
Use TRY...CATCH for:
- Complex error handling logic
- Multiple specific catch blocks needed
- Modern structured programming style
Implementation Notes
- Implemented in Rust under
src/basic/keywords/errors/on_error.rs - Error state is thread-local per script execution
- Error trapping scope is global to the script (not block-scoped)
CLEAR ERRORresets bothERRORflag andERROR MESSAGE- Maximum error message length: 4096 characters
Related Keywords
- THROW — Raise custom errors
- ASSERT — Assert conditions
- PRINT — Debug output for error logging
- WAIT — Delay before retry
Summary
ON ERROR RESUME NEXT provides BASIC error handling for BASIC scripts, allowing graceful handling of errors without script termination. Always check ERROR after risky operations, use CLEAR ERROR before subsequent operations, and disable error trapping with ON ERROR GOTO 0 when protection is no longer needed. For user-facing errors, provide clear messages while logging technical details for debugging.