Skip to content

Fallible Channels (T ! E)

Wysna does not have untyped, out-of-band exceptions (such as throw or try/catch). Instead, functions that can fail declare their potential error types as part of the return signature using the fallible channel syntax: T ! E.

  • T is the type returned upon success.
  • E is the type returned upon failure.
## A function that returns an int or an error string
fn parse_port(input: str) -> int ! str {
let port = int(input)
if port < 1 or port > 65535 {
return error("Port number must be between 1 and 65535")
}
return port
}

When calling a fallible function inside another function that also returns a compatible error channel, use the postfix ? operator. If the expression evaluates to an error, the enclosing function returns the error immediately:

struct ServerConfig {
host: str
port: int
}
fn load_server_config(env_port: str) -> ServerConfig ! str {
# If parse_port fails, load_server_config immediately returns the error
let valid_port = parse_port(env_port)?
return ServerConfig {
host: "0.0.0.0",
port: valid_port,
}
}

This prevents repetitive error-checking boilerplate while maintaining 100% type safety and explicit execution flow.


To handle an error locally and provide a fallback or recovery logic, use the else err { ... } block:

fn start_server(port_str: str) -> unit {
let port = parse_port(port_str) else err {
print("[WARNING] Invalid port provided:", err)
print("[INFO] Defaulting to fallback port 8080")
8080 # Yields 8080 into `port`
}
print("Server initialized on port:", port)
}
fn main() -> unit {
start_server("999999") # Exceeds 65535, triggers recovery
start_server("3000") # Valid, sets port directly
}
  1. Explicit Control Flow: You can tell by reading the function signature whether it can fail.
  2. Zero Hidden Crashes: The compiler refuses to compile code that ignores a fallible channel.
  3. No Hidden Unwinding Overhead: In generated C99 code, error returns compile into simple return codes and value structs without heavy stack unwinding.