Run cleanup code after a try block regardless of whether an exception occurred.

← Control Flow · Ref: Q1155

finally always runs after try/catch:

  try
    stdout.println("working")
  catch
    -> ex as Exception
    stdout.println(ex.reason())
  finally
    stdout.println("cleanup")

The finally block executes whether the try succeeds or catch handles an exception.

See Q1154 for basic try/catch.

Example

defines module qa.controlflow.trywithfinally

  defines program

    TryWithFinallyDemo()
      stdout <- Stdout()

      //Success path — finally still runs
      try
        stdout.println("Working")
      catch
        -> ex as Exception
        stdout.println(ex.reason())
      finally
        stdout.println("Cleanup runs regardless")

Common mistakes

E01010 — EK9 uses indentation, not braces. The finally block is a peer of try and catch.

Incorrect:

      finally {
        System.out.println("cleanup");
      }

Correct:

      finally
        stdout.println("Cleanup runs regardless")
Other ways to ask this
  • I need a finally block that always runs after try/catch
  • In Java I'd use try-finally for guaranteed cleanup. Write the EK9 equivalent
  • Given an operation that might fail, ensure cleanup runs either way
  • Execute teardown logic after both success and failure paths

Coming from another language?

Java: try { } catch { } finally { }. Python: try/except/finally. Go: defer. EK9: try/catch/finally — same structure as Java.

Keywords: finally, try, teardown, exception, always, cleanup