Error Handling
Unrecoverable Errors
Exit codes terminate execution immediately:
if invalid_condition:
exit(1)Unhandled exceptions also become unrecoverable:
raise Exception("Critical error") # Becomes exit(1)UserError
User-generated errors with UTF-8 encoded messages:
# Can be caught in current sub-vm
raise gl.UserError("Invalid input")
# Immediate user error, more efficient but can't be caught
gl.user_error_immediate("Insufficient funds")VMError
VM-generated errors with predefined string codes:
# Non-zero exit codes become VMError
exit(1) # Results in VMError with specific code
# Resource limit violations also trigger VMError
# (handled automatically by the VM)Catching UserError
Handle user errors from sub-VMs:
def risky_operation():
raise gl.UserError("Operation failed")
try:
result = gl.eq_principle.strict_eq(risky_operation)
except gl.UserError as e:
print(f"Caught user error: {e.message}")Error Propagation
Errors flow from non-deterministic to deterministic code:
def nondet_block():
if some_condition:
raise gl.UserError("INVALID_STATE")
return "success"
try:
gl.eq_principle.strict_eq(nondet_block)
except gl.UserError as e:
if e.message == "INVALID_STATE":
# Handle specific error condition
passVM Result Types
GenVM produces four result types:
- Return - Successful execution with encoded result
- VMError - VM errors (exit codes, resource limits)
- UserError - User-generated errors with UTF-8 messages
- InternalError - Critical VM failures (not visible to contracts)