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
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: error, finally, try, catch, data-in, arrow, throw, exception, handle