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:

  result <- try
    parseInput(rawText)
  catch
    -> ex as Exception
    "default value"

GUARD TRY

Try can use a guard variable:

  try result <- riskyComputation()
    stdout.println(result)
  catch
    -> ex as Exception
    stdout.println(`Failed: ${ex}`)

EXCEPTION TYPES

EK9 has a fixed exception hierarchy:
- Exception (base type)
Use '$' on an exception to get its message as String.

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(`Error: ${ex}`)

      // Try/catch/finally — finally always runs
      try
        result <- safeDivide(100, 4)
        stdout.println(`100 / 4 = ${result}`)
      catch
        -> ex as Exception
        stdout.println(`Failed: ${ex}`)
      finally
        stdout.println("Division complete")

      // Nested try/catch — works like Java
      try
        firstResult <- safeDivide(20, 5)
        stdout.println(`20 / 5 = ${firstResult}`)
      catch
        -> ex as Exception
        stdout.println(`Nested failed: ${ex}`)

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:

-> ex as String

Correct:

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