Versuch / fang (try/catch)

Catch runtime errors with `versuch { } fang (err) { }`: the Rain equivalent of try/catch.

Wrap risky code in a **versuch** block (try). If a runtime error happens inside it, execution jumps to the matching **fang** block (catch) instead of crashing the program.

The **fang** keyword is always followed by (name): one variable that receives the error message as a string, then { ... } for the handler body.

If the versuch block finishes without error, the fang block is **skipped** entirely.

Errors only propagate to an outer versuch when no inner fang handles them. Without any matching handler, Rain prints the error to stderr and exits with code **70**.

Use versuch/fang in HTTP route handlers to return 500 responses instead of killing the server. See the **http** module docs.

Basic catch

Runtime errors inside `versuch` jump to `fang` instead of exiting the program.

Basic catch
versuch {
  var arr = #[1, 2, 3];
  print arr#[99];
} fang (err) {
  print "caught:";
  print err;
}
print "program continues";
output
caught:
Array index out of bounds.
program continues

Success path: fang skipped

If nothing fails, the `fang` block never runs.

Success path: fang skipped
versuch {
  var x = 42;
  print x;
} fang (err) {
  print "should not run";
}
print "done";
output
42
done

Nested versuch

Inner `fang` handles its own errors; execution continues in the outer `versuch`.

Nested versuch
versuch {
  versuch {
    var a = nil;
    print a.boom;
  } fang (err) {
    print "inner:" + err;
  }
  print "after inner";
} fang (err) {
  print "outer:" + err;
}
output
inner:Only instances have properties.
after inner

Outer catches when inner succeeds

An error after an inner handler finishes propagates to the outer `fang`.

Outer catches when inner succeeds
versuch {
  versuch {
    print 1;
  } fang (err) {
    print "inner fail";
  }
  print noSuchVar;
} fang (err) {
  print err;
}
output
1
Undefined variable 'noSuchVar'.

versuch inside a function

Wrap risky logic in a helper and return a fallback value on failure.

versuch inside a function
fun safeGet(arr, index) {
  versuch {
    return arr#[index];
  } fang (err) {
    return -1;
  }
}

print safeGet(#[10, 20], 1);
print safeGet(#[10, 20], 99);
output
20
-1

HTTP handler pattern

Return a 500 response from `fang` so one bad request does not kill the server.

handler.rn
benutzen "http";

fun createUser(req) {
  versuch {
    var data = json::parse(req.body);
    if (data.email == nil) {
      return http::response(400, "email required");
    }
    return http::jsonResponse(201, "{\"ok\":true}");
  } fang (err) {
    return http::response(500, err);
  }
}

http::post("/users", createUser);
http::listen(8080);

Syntax

`versuch` runs code that might fail; `fang` receives the error message as a string.

SymbolDescription
versuch { } (try)Try block: code that may throw a runtime error
fang (err) { } (catch)Catch block: `err` is a string with the error message

Errors caught by versuch

Common runtime failures you can handle instead of crashing the program.

SymbolDescriptionExample
Array index out of bounds`arr#[99]` when the index is outside the array
versuch { print #[1, 2]#[5]; } fang (err) { print err; }
Non-number indexIndexing with a value that isn't a number
versuch { var idx = "hi"; print #[1]#[idx]; } fang (err) { print err; }
Index non-arrayUsing `#[ ]` on something that isn't an array
versuch { print (42)#[0]; } fang (err) { print err; }
Non-string map keyUsing a non-string value as a map key
versuch { var m = {"a": 1}; print m[42]; } fang (err) { print err; }
Nil property accessReading a field on `nil`
versuch { var x = nil; print x.field; } fang (err) { print err; }
Undefined variableUsing a name that was never declared
versuch { print missing; } fang (err) { print err; }
Type mismatch (+)Operands that can't combine with `+` (e.g. `nil`, arrays, or number + boolean)
versuch { print nil + "x"; } fang (err) { print err; }
Unary negateNegating a non-number with `-`
versuch { print -"hi"; } fang (err) { print err; }
Wrong arityCalling a function with too few or too many arguments
fun pair(a, b) { return a + b; } versuch { pair(1); } fang (err) { print err; }
Call non-callableInvoking a number or other non-function value
versuch { var x = 42; x(); } fang (err) { print err; }
Array method errorse.g. `pop()` on an empty array
versuch { var a = #[]; a->pop(); } fang (err) { print err; }
Errors in called functionsStack unwinds to the nearest active `versuch`
fun risky() { var x = nil; x.boom; } versuch { risky(); } fang (err) { print err; }

Notes