Skip to content


Folders and files

Last commit message
Last commit date

Latest commit



64 Commits

Repository files navigation


CI Codecov

Rust-like safe error handling in Julia

ErrorTypes is a simple implementation of Rust-like error handling in Julia. Its goal is to increase safety of Julia code internally in packages by providing easy-to-use, zero-cost handling for recoverable errors.

Read more in the documentation.

Example usage

This simple example shows a function that has one obvious error state, namely that there is no second field. This can be modelled with the Option type:

function second_csv_field(s::Union{String, SubString{String}})::Option{SubString{String}}
    p = nothing
    for i in 1:ncodeunits(s)
        if codeunit(s, i) == UInt8(',')
            isnothing(p) || return some(SubString(s, p, prevind(s, i))) 
            p = i + 1
    (isnothing(p) | (p == ncodeunits(s) + 1)) ? none : some(SubString(s, p, ncodeunits(s)))

This example shows usage of the type Result. When there are multiple error modes, we may encode the error state however we want, here in an Enum:

# corresponds to the error codes of libdeflate
@enum DecompressError::UInt8 BadData TooShort TooLong

function decompress(outbytes, inbytes)::Result{Int32, DecompressError}
    (n_bytes, errorcode) = ccall( ... ) # Call omitted here, returns an (Int32, Int32)
    if !iszero(errorcode)
        return Err(DecompressError(errorcode - 1))
        return Ok(n_bytes)

You can of course mix and match regular exceptions and error types. That is useful when you have both unrecoverable and recoverable errors. In the following example, I'm getting the first field of first row of a comma separated file. We expect the file and its header to be present, and the second row to be tab-separated, and will error if it's not, but a valid CSV file may contain no rows other than the header:

function first_field(io::IO)::Option{String}
    lines = eachline(io)
    if! startswith(first(iterate(lines)), "#Name\t")
        error("In file, expected header to begin with: \"#Name\\t\"")
    nextit = iterate(lines)
    isnothing(nextit) && return none
    line = first(nextit)
    isempty(line) && return none
    tab_pos::Int = findfirst(isequal('\t'), line)

Again, please read the documentation.