Error Handling
Flowa supports structured exception handling with try, catch, and finally blocks for robust error management.
Basic Try-Catch
Handle errors gracefully with try-catch blocks:
try {
let result = riskyOperation();
} catch (e) {
print("Error: " + e);
}Try-Catch-Finally
Use finally to ensure cleanup code always executes:
try {
let file = openFile("data.txt");
processFile(file);
} catch (e) {
print("Error: " + e["message"]);
} finally {
print("Cleanup executed");
}Throwing Errors
Throw custom errors with the throw statement:
func validateAge(age) {
if (age < 0) {
throw "Age cannot be negative";
}
if (age > 150) {
throw { "code": 400, "message": "Invalid age" };
}
return true;
}Error Object Properties
When catching errors, the error object contains useful information:
try {
validateAge(-5);
} catch (e) {
// For runtime errors, e contains:
// - e["message"] - error description
// - e["type"] - error type (e.g., "RuntimeError")
// - e["line"] - line number where error occurred
print("Error at line " + e["line"] + ": " + e["message"]);
}Error Object Properties:
message- The error message/descriptiontype- The type of error (e.g., "RuntimeError")line- Line number where the error occurred (when available)
Catching Structured Errors
Handle different types of errors:
try {
let data = json.parse(invalid_json);
let result = divide(10, 0);
} catch (e) {
if (e["type"] == "ParseError") {
print("JSON parsing failed: " + e["message"]);
} else if (e["type"] == "RuntimeError") {
print("Runtime error: " + e["message"]);
} else {
print("Unknown error: " + e["message"]);
}
}Practical Examples
File Operations with Error Handling
func readFileSafely(filename) {
try {
let content = fs.readFile(filename);
if (content == null) {
throw "File not found or could not be read";
}
return content;
} catch (e) {
log.error("Failed to read file: " + filename);
log.error("Error: " + e["message"]);
return null;
}
}Database Operations
func getUserById(db, id) {
try {
let result = sqlite.query(db, "SELECT * FROM users WHERE id = " + tostring(id));
if (result == null || len(result) == 0) {
throw { "code": 404, "message": "User not found" };
}
return result[0];
} catch (e) {
log.error("Database error: " + e["message"]);
return null;
} finally {
// Cleanup if needed
}
}HTTP Request Error Handling
func handleRequest(req, res) {
try {
let data = json.parse(req.body);
if (!("username" in data)) {
throw { "code": 400, "message": "Missing username" };
}
// Process request
res.writeHead(200, {"Content-Type": "application/json"});
res.end(json.stringify({"status": "success"}));
} catch (e) {
let status_code = 500;
if ("code" in e) {
status_code = e["code"];
}
res.writeHead(status_code, {"Content-Type": "application/json"});
res.end(json.stringify({"error": e["message"]}));
}
}Validation with Custom Errors
func validateUser(user) {
if (type(user) != "hash") {
throw { "type": "ValidationError", "message": "User must be a hash" };
}
if (!("email" in user)) {
throw { "type": "ValidationError", "message": "Email is required" };
}
if (!contains(user["email"], "@")) {
throw { "type": "ValidationError", "message": "Invalid email format" };
}
return true;
}
// Usage
try {
validateUser({"name": "Alice"}); // Missing email
} catch (e) {
if (e["type"] == "ValidationError") {
print("Validation failed: " + e["message"]);
}
}Best Practices
1. Use Specific Error Messages
// Good
throw "Division by zero is not allowed";
// Better
throw {
code: 400,
message: "Division by zero is not allowed",
field: "divisor",
};2. Always Handle Errors
// Bad - unhandled error
let result = divide(a, b);
// Good - handle potential errors
try {
let result = divide(a, b);
print(result);
} catch (e) {
print("Error: " + e["message"]);
}3. Use Finally for Cleanup
let db = null;
try {
db = sqlite.open("app.db");
// Use database
} catch (e) {
log.error("Database error: " + e["message"]);
} finally {
if (db != null) {
sqlite.close(db);
}
}4. Don't Swallow Errors
// Bad - error is hidden
try {
riskyOperation();
} catch (e) {
// Silent failure
}
// Good - log or handle error
try {
riskyOperation();
} catch (e) {
log.error("Operation failed: " + e["message"]);
// Handle appropriately
}Next Steps
- Functions - Learn about function error handling
- Standard Library - See module-specific error handling
- Troubleshooting - Common error solutions