Skip to content

0.25.0

Released: June 2026

This release upgrades Stove's two most impactful runtime dependencies — Ktor 3.5 (HTTP client) and kotlinx-coroutines 1.11. Both are backward-compatible at the source level, but each can surface a runtime issue in downstream projects depending on how your own dependency graph is pinned. This note exists to make those two cases obvious so you can fix them in minutes.


Dependency Updates

Dependency From To
Ktor 3.4.3 3.5.0
kotlinx-coroutines 1.10.2 1.11.0

Stove is compiled and tested against these versions. The two sections below cover the only behavior changes that can affect your suite.


Heads-up: kotlinx-coroutines 1.11 and NoSuchMethodError: runBlockingK

kotlinx-coroutines 1.11 introduced a new internal entrypoint, BuildersKt.runBlockingK. When the Kotlin compiler compiles a runBlocking { } call against 1.11, it now emits a call to runBlockingK$default. Stove is compiled against 1.11, so Stove's bytecode references that method.

If your test runtime ends up resolving an older kotlinx-coroutines-core-jvm (1.8.x / 1.10.x), the method won't exist and you'll see:

java.lang.NoSuchMethodError: 'java.lang.Object kotlinx.coroutines.BuildersKt.runBlockingK$default(
    kotlin.coroutines.CoroutineContext, kotlin.jvm.functions.Function2, int, java.lang.Object)'
    at com.trendyol.stove.system.Stove.close(Stove.kt:...)

Why it happens

This is almost always a transitive BOM dragging coroutines backward. The most common culprit is the Spring Boot dependency management plugin (io.spring.dependency-management): Spring Boot 3.5.x pins kotlin-coroutines.version to 1.8.1 via its BOM, and that managed version overrides Gradle's own resolutionStrategy.force — so a plain force(...) won't fix it.

You can confirm the downgrade with:

./gradlew :your-module:dependencyInsight \
  --configuration testRuntimeClasspath \
  --dependency kotlinx-coroutines-core-jvm

If you see ... -> 1.8.1 (or any version below 1.11), you're affected.

The fix

If you use the Spring dependency management plugin, override the BOM property in the affected module's build.gradle.kts:

// Override the Spring Boot BOM's kotlin-coroutines pin so the runtime matches
// what Stove (and your code) were compiled against.
extra["kotlin-coroutines.version"] = "1.11.0"

If you do NOT use a managing BOM, a resolution strategy is enough:

configurations.all {
    resolutionStrategy.eachDependency {
        if (requested.group == "org.jetbrains.kotlinx" &&
            requested.name.startsWith("kotlinx-coroutines")
        ) {
            useVersion("1.11.0")
        }
    }
}

Either way, re-run dependencyInsight and confirm kotlinx-coroutines-core-jvm resolves to 1.11.0 everywhere.


Heads-up: Ktor 3.5 quotes multipart Content-Disposition parameters

Ktor 3.5 now quotes the name parameter in multipart form-data Content-Disposition headers, per RFC 7578:

# Ktor 3.4 and earlier
Content-Disposition: form-data; name=name

# Ktor 3.5
Content-Disposition: form-data; name="name"

Stove's postMultipartAndExpectResponse / StoveMultiPartContent use Ktor's formData {} under the hood, so any multipart request Stove sends now carries the quoted form.

Who is affected

Only tests that assert on the raw Content-Disposition header of a multipart part — typically WireMock multipart stubs:

// Before — fails against Ktor 3.5
aMultipart()
    .withHeader("Content-Disposition", equalTo("form-data; name=name"))

// After
aMultipart()
    .withHeader("Content-Disposition", equalTo("form-data; name=\"name\""))

Functional behavior is unchanged — servers parse both forms. You only need to update exact-match stub expectations. If you match the field name loosely (e.g. WireMock's aMultipart().withName("name")) you are unaffected.


Migration Guide

From 0.24.0 to 0.25.0

No Stove API changes. The two items below are the only things to check after upgrading.

  1. Run your suite. If you hit NoSuchMethodError: ... runBlockingK, apply the coroutines fix above (BOM property override for Spring users, resolution strategy otherwise).
  2. Multipart stubs. If any multipart Content-Disposition assertion fails on a quoting mismatch, update the expected value to the quoted form (name="...").

Everything else is a drop-in upgrade.