Lesson 4: Failures as part of the contract

Treat errors as data — Option, Result, and the ? operator.

Goal

In one sentence: return and propagate errors explicitly and scannably.

Code

public func fetchBalance(account: ref Account): Result<int, str> {
    if account.active == false {
        return Result.Err("account disabled")
    }
    return Result.Ok(account.balance)
}

The type Result<int, str> says the function either returns an int (Result.Ok(...)) or an error message (Result.Err(...)). No hidden exceptions behind the scenes.

Propagating with ?

public func summary(account: ref Account): Result<str, str> {
    let balance = fetchBalance(account)?
    return Result.Ok("Balance: " + balance)
}

The ? shortens propagation: on Err, the whole function returns that error; on Ok, you get the value.

Try it

Remove the ? from fetchBalance(account) and watch the compiler ask you to handle the Result explicitly. It will not let an error slip through without you deciding what to do.

Tip

Option<T> works the same way: Option.Some(...) or Option.None, no null. Combine Option and Result to model “may not exist” and “may fail” as distinct things.

Errors as values keep the error flow visible in the code itself — you can see exactly where an error might arise.