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
- Rust-like
anyhow { }result builder bind()for early-return error propagation (Rust?).context()andwithContext()for rich error messagesbail()for immediate failureensure()/ensureNotNull()helpers- Convert Kotlin
Resultto AnyhowResult - Typed + string + throwable errors
sourceSets {
commonMain.dependencies {
implementation("io.github.itsvks19:anyhowkt:<version>")
}
}dependencies {
implementation("io.github.itsvks19:anyhowkt:<version>")
}val result = anyhow {
val a = parseInt("10").bind()
val b = parseInt("20").bind()
a + b
}val value: Int = result.unwrap()Rust:
let value = compute()?;Kotlin (AnyhowKt):
val value = compute().bind()This works inside anyhow { } blocks.
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
...
val result = anyhow {
if (user == null) {
bail("User not found")
}
user.name
}anyhow {
ensure(x > 0) { "x must be positive" }
ensureNotNull(user) { "user is required" }
ensureEquals(a, b) { "values must match" }
}val kResult: Result<Int> = runCatching { riskyCall() }
val result: AnyhowResult<Int> = kResult.anyhow()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 (anyhow) |
Kotlin (AnyhowKt) |
|---|---|
anyhow::Result<T> |
AnyhowResult<T> |
? |
.bind() |
bail!("msg") |
bail("msg") |
.context("msg") |
.context("msg") |
ensure!(cond) |
ensure(cond) |
MIT License.
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 ✨