Skip to content
This repository was archived by the owner on Dec 28, 2025. It is now read-only.

itsvks19/anyhowkt

Repository files navigation

AnyhowKt

Rust-style error handling for Kotlin.

AnyhowKt is a Kotlin Multiplatform (KMP) library inspired by Rust's anyhow crate. It provides a simple, powerful, and expressive way to handle errors with:

  • Context-aware errors
  • Short-circuiting with bind() (Rust ?-like behavior)
  • Typed and untyped error sources
  • bail, ensure, and structured error propagation
  • Works across JVM, Android, iOS, JS, Native

Features

  • Rust-like anyhow { } result builder
  • bind() for early-return error propagation (Rust ?)
  • .context() and withContext() for rich error messages
  • bail() for immediate failure
  • ensure() / ensureNotNull() helpers
  • Convert Kotlin Result to AnyhowResult
  • Typed + string + throwable errors

Installation

Gradle (Kotlin DSL) [Multiplatform]

Maven Central Version

sourceSets {
    commonMain.dependencies {
        implementation("io.github.itsvks19:anyhowkt:<version>")
    }
}

Gradle (Kotlin DSL) [Android/Jvm]

dependencies {
    implementation("io.github.itsvks19:anyhowkt:<version>")
}

Basic Usage

val result = anyhow {
    val a = parseInt("10").bind()
    val b = parseInt("20").bind()
    a + b
}

Unwrapping

val value: Int = result.unwrap()

Rust ? Equivalent in Kotlin

Rust:

let value = compute()?;

Kotlin (AnyhowKt):

val value = compute().bind()

This works inside anyhow { } blocks.

Contextual Errors

val result = anyhow {
    val file = readFile("config.json")
        .anyhowResult { "file not found" }
        .bind() // Early return on readFile failure

    parseConfig(file)
        .anyhow()
        .bind()
}.context("Failed to load application config")

Error output becomes:

Failed to load application config
Caused by: file not found
...

bail – Early Exit

val result = anyhow {
    if (user == null) {
        bail("User not found")
    }
    user.name
}

ensure Helpers

anyhow {
    ensure(x > 0) { "x must be positive" }
    ensureNotNull(user) { "user is required" }
    ensureEquals(a, b) { "values must match" }
}

Kotlin Result -> AnyhowResult

val kResult: Result<Int> = runCatching { riskyCall() }

val result: AnyhowResult<Int> = kResult.anyhow()

Plug-in for IntelliJ-based IDEs

This library internally uses arrow-kt.

If you are using an IntelliJ IDEA or any other IDE from JetBrains, we strongly recommend installing the Arrow plug-in. The plug-in helps fix common problems, especially in the realm of typed errors and suggests more idiomatic alternatives when available.

Rust vs Kotlin Example

Rust (anyhow) Kotlin (AnyhowKt)
anyhow::Result<T> AnyhowResult<T>
? .bind()
bail!("msg") bail("msg")
.context("msg") .context("msg")
ensure!(cond) ensure(cond)

License

MIT License.

Contributing

PRs and feature requests are welcome! If you'd like to help add:

  • richer formatting
  • better JS/iOS backtraces
  • or compiler plugin support

feel free to contribute ✨