problem-details-ktor

Ktor server integration: respond with a problem document, and turn thrown exceptions into problem documents through StatusPages.

This module never depends on problem-details-xml. That edge is the reason the library is split at all — an application that only emits JSON does not resolve an XML parser. XML support is a separate artifact declaring its own registration function, so a missing dependency is a compile error at the call site rather than a NoClassDefFoundError at runtime.

Published for jvm, js, wasmJs, linuxX64, linuxArm64, mingwX64, macosArm64, iosArm64 and iosSimulatorArm64. Depend on the plain coordinates from commonMain and Gradle picks the variant.

What it does not do

It does not reimplement dispatch or content negotiation. Everything here generates the calls you would otherwise hand-write into StatusPages' and ContentNegotiation's own configuration DSLs. Nearest-parent-class exception resolution and Accept quality-value matching stay Ktor's, with Ktor's semantics and Ktor's bug fixes.

Where to start

install(ContentNegotiation) { problemJson() }

install(StatusPages) {
problemDetails {
standardStatusCodes()
map<IllegalArgumentException> { _, e -> problem { status = 400; detail = e.message } }
}
}

Then respond from a route with io.github.ilyankin.rfc9457.ktor.respondProblem, or just throw and let the catalog answer.

The catalog becomes immutable when the problemDetails { ... } or problemCatalog { ... } builder block ends. Declare all mappings and customizers inside that block; late mutation is rejected so runtime handling and generated documentation cannot drift apart.

Packages

Link copied to clipboard
common

Five behaviours here are decisions rather than defaults, and each is pinned by a test: