Skip to content

Declare Ktor failures with Spine and Arrow

Spine provides helper functions for the Arrow Typed Errors library. They are based on the Raise DSL and context parameters, which you may need to enable.

Declaring failures

Declaring failures with the Arrow compatibility modules is identical to declaring failures with the base Spine module. Read the dedicated article.

Server-side

Add a dependency on the server-arrow module:

build.gradle.kts
plugins {
    kotlin("jvm") version "…"
}

dependencies {
    implementation("dev.opensavvy.spine:server-arrow:VERSION") //(1)!
}
  1. List of versions
build.gradle.kts
plugins {
    kotlin("multiplatform") version "…"
}

kotlin {
    jvm()
    linuxX64()
    // add any other platform you want to target…

    sourceSets.commonMain.dependencies {
        api("dev.opensavvy.spine:server-arrow:VERSION") //(1)!
    }
}
  1. List of versions

When declaring routes, replace route by routeWithRaise:

the Arrow module adds:

routeWithRaise(Users.User.edit) {
    // …
}

The DSL is identical to usual Spine, but adds support for Raise for failure management.

For example, you can replace:

route(Users.User.edit) {
    if (body.user.name.length < 5)
        fail(UsernameTooShort)

    // …
}

by:

routeWithRaise(Users.User.edit) {
    ensure(body.user.name.length >= 5) { UsernameTooShort }
}
Raise in Ktor endpoints without Spine

If you want to use the Raise DSL with Ktor, but don't want to use Spine, you can use our module server-arrow-independent which adds the function raise to regular Ktor endpoints.

Client-side

Add a dependency on the client-arrow module:

build.gradle.kts
plugins {
    kotlin("jvm") version "…"
}

dependencies {
    implementation("dev.opensavvy.spine:client-arrow:VERSION") //(1)!
}
  1. List of versions
build.gradle.kts
plugins {
    kotlin("multiplatform") version "…"
}

kotlin {
    jvm()
    linuxX64()
    // add any other platform you want to target…

    sourceSets.commonMain.dependencies {
        api("dev.opensavvy.spine:client-arrow:VERSION") //(1)!
    }
}
  1. List of versions

In addition to .bodyOrThrow(), .bodyOrNull() and .handle() (learn more), this module adds the .body() function which raises each failure.

context(Raise<NotFound>)
fun HttpClient.getUser(id: String): User =
    this.request(Users / User(id) / User.get).body()

fun HttpClient.getUserOrNull(id: String): User? =
    recover(block = { getUser(id) }, recover = { null })