How do try/catch/finally work in EK9?
← Control Flow · Ref: Q902
EK9 has try/catch/finally similar to Java, but the catch clause uses '->' for the exception parameter — like Go's 'in' parameter or Ada's 'in' port.
BASIC TRY/CATCH
try riskyOperation() catch -> ex as Exception stdout.println(`Error: ${ex}`) the -> means 'data coming in'
IMPORTANT: The catch uses '->' on its own line, like function parameters. The exception is data flowing IN to the catch handler.
TRY/CATCH/FINALLY
try openConnection() sendRequest() catch -> ex as Exception logError(ex) finally closeConnection() always runs, like Java's finally
TRY AS EXPRESSION
Like switch, try can be an expression. It needs a returning variable that the body (and the catch) assign:
result <- try <- rtn as String: "default value" rtn: parseInput(rawText) catch -> ex as Exception rtn: "recovered"
GUARD TRY
Try can use a guard variable:
try result <- riskyComputation() stdout.println(result) catch -> ex as Exception stdout.println(`Failed: ${ex}`)
EXCEPTION TYPES
Exception is the base type and is declared 'as open', so you can extend it with your own exception types.
Use '$' on an exception to get its type and reason as a String ('Exception: <reason>'); ex.reason() gives just the reason text.
NO CHECKED EXCEPTIONS
EK9 does not have checked exceptions. All exceptions are runtime.
See Q130 for control flow. See Q893 for section headers.
Example
#!ek9 defines module qa.controlflow.trycatch defines function <?- Basic function that may throw. -?> safeDivide() as pure -> numerator as Integer denominator as Integer <- rtn as Float: #^ numerator / #^ denominator defines program TryCatchDemo() stdout <- Stdout() // Basic try/catch — note -> on catch for exception parameter // Like Go/Ada: -> means 'data flowing in' to the handler try quotient <- safeDivide(10, 2) stdout.println(`10 / 2 = ${quotient}`) catch -> ex as Exception stdout.println(ex.reason()) // Try/catch/finally — finally always runs try result <- safeDivide(100, 4) stdout.println(`100 / 4 = ${result}`) catch -> ex as Exception stdout.println(ex.reason()) finally stdout.println("Division complete") // Nested try/catch: the inner try sits inside the outer try body try firstResult <- safeDivide(20, 5) stdout.println(`20 / 5 = ${firstResult}`) try secondResult <- safeDivide(8, 2) stdout.println(`inner: ${secondResult}`) catch -> ex as Exception stdout.println(ex.reason()) catch -> ex as Exception stdout.println(ex.reason()) // Try as an expression: the returning variable carries the value parsed <- try <- rtn as String: "default value" rtn: `${safeDivide(9, 3)}` catch -> ex as Exception rtn: `failed: ${ex.reason()}` stdout.println(`parsed: ${parsed}`)
Common mistakes
E04030 — The catch clause requires an Exception type, not String or other types. The variable after -> must be declared 'as Exception'. See ek9 -h E04030 for details.
Incorrect:
catch -> ex as String stdout.println(ex) finally
Correct:
catch -> ex as Exception stdout.println(ex.reason()) finally
Other ways to ask this
- How do I catch exceptions in EK9?
- What is the catch syntax in EK9?
- Does EK9 have try/catch?
- How do I handle exceptions in EK9?
Coming from another language?
Java: catch (Exception e) { ... } — EK9 uses -> ex as Exception on separate line. Go: if err != nil — EK9 has try/catch, not error values. Python: except Exception as e: — similar but EK9 uses -> prefix. Kotlin: catch (e: Exception) — EK9 uses -> for incoming data. Rust: Result and ? operator — EK9 has both try/catch and Result type. EK9: catch with -> ex as Exception — the -> means 'data flowing in' like Go/Ada parameter ports.
Keywords: arrow, catch, data-in, error, exception, finally, handle, throw, try