Error Handling

ArgumentError, BoundsError, DomainError, DimensionMismatch, DivideError, ErrorException, InexactError, KeyError, MethodError, OverflowError, StackOverflowError, TypeError, UndefVarError, UndefRefError, StringIndexError, InterruptException, SystemError, EOFE…

18.1 Throwing and catching

function safe_sqrt(x)
    x < 0 && throw(DomainError(x, "negative input"))
    sqrt(x)
end

try
    safe_sqrt(-1)
catch e
    if e isa DomainError
        println("Domain error: ", e.msg)
    else
        rethrow()
    end
finally
    println("always runs")
end

result = try parse(Int, "abc") catch; -1 end
error("Something went wrong")          # throws ErrorException
@assert x > 0 "x must be positive"     # assertion (may be disabled)

18.2 Built-in exceptions

ArgumentError, BoundsError, DomainError, DimensionMismatch, DivideError, ErrorException, InexactError, KeyError, MethodError, OverflowError, StackOverflowError, TypeError, UndefVarError, UndefRefError, StringIndexError, InterruptException, SystemError, EOFError, OutOfMemoryError, TaskFailedException, CompositeException.

18.3 Custom exceptions

struct InsufficientFunds <: Exception
    needed::Float64
end
Base.showerror(io::IO, e::InsufficientFunds) = print(io, "insufficient funds: need ", e.needed)

throw(InsufficientFunds(25.0))

18.4 Stack traces & warnings

Logging is configurable via Logging (global_logger(ConsoleLogger(stderr, Logging.Debug))) and packages like LoggingExtras.jl.

try
    error("boom")
catch e
    showerror(stderr, e, catch_backtrace())
end
current_exceptions()            # exception stack (1.7+)
@warn "Low memory" free_mb=120
@info "Starting" n=10
@debug "details"                # enable with ENV["JULIA_DEBUG"] = "Main"
@error "Failed" exception=(e, catch_backtrace())

18.5 Errors vs return values

Julia idiomatically throws exceptions for errors (they're not used for control flow in hot loops — they're slow). For expected "no value" cases return nothing (findfirst, tryparse) and check with isnothing/something.