Error handling
attempt / rescue
attempt wraps code that might fail. rescue catches the error:
lhj
attempt:
forge x = int("not a number")
rescue e:
echo "Error: {e}"Output:
lhj
Error: invalid literal for int() with base 10: 'not a number'rescue with type filtering
You can match specific error types:
lhj
attempt:
forge result = 10 / 0
rescue ZeroDivisionError as e:
echo "Division by zero: {e}"
rescue RuntimeError as e:
echo "Runtime problem: {e}"
rescue e:
echo "Something else: {e}"finally — always runs
lhj
attempt:
forge f = os.open("data.txt")
forge content = f.read()
rescue e:
echo "Read failed: {e}"
finally:
echo "Cleanup done"The finally block runs whether the attempt succeeded or not.
raise — throwing errors
lhj
blade divide(a, b):
blade b == 0:
raise "Cannot divide by zero"
release a / b
attempt:
echo divide(10, 0)
rescue e:
echo e ## Cannot divide by zeroCustom error types
Create a class that extends a base error:
lhj
ritual ValidationError extends RuntimeError:
blade awaken(self, field: str, msg: str):
self.field = field
self.msg = msg
invoke awaken(self, "{field}: {msg}")
blade validate_hp(hp: int):
blade hp < 0:
raise ValidationError("hp", "must be non-negative, got {hp}")
blade hp > 1000:
raise ValidationError("hp", "maximum is 1000, got {hp}")
attempt:
validate_hp(-5)
rescue ValidationError as e:
echo "Validation failed on field '{e.field}': {e.msg}"Error types
| Type | When raised |
|---|---|
RuntimeError | General interpreter errors |
NameError | Undefined variable |
TypeError | Wrong type for an operation |
ValueError | Right type, wrong value |
ZeroDivisionError | Division or modulo by zero |
IndexError | List index out of range |
KeyError | Dict key not found |
AttributeError | Object has no such attribute |
Propagation
If an error isn't caught in the current function, it propagates up the call stack. If it reaches the top level without being caught, the interpreter prints the error and exits.
lhj
blade inner():
raise "boom"
blade middle():
inner()
blade outer():
attempt:
middle()
rescue e:
echo "Caught in outer: {e}"
outer() ## Caught in outer: boom