Skip to content

IO Exception when listing s3 objects in bucket #1214

@Sebo11

Description

@Sebo11

Describe the bug

When executing below code it randomly happens that the call to s3 fails with an IO Exception (exception is inserted below). I cannot put a precise number on it but I guess this happens once every 20 request or so. It can be "fixed" when the attempts are upped to more than 5. Because when this happens it failes always exactly 5 times with the 6th attempt going trough somehow.

I cannot explain why this occurs and why it always fails 5 times with the 6th attempt going trough.

import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.ListObjectsV2Request
import jakarta.inject.Singleton
import io.micronaut.context.annotation.Property


@Singleton
class Service(private val s3: S3Client) : Logger {
    @Property(name = "bucket-name")
    private lateinit var awsbucket: String

    suspend fun listObjects(uuid: UUID): List<Object>? {
        val request = ListObjectsV2Request {
            bucket = awsbucket
            prefix = "documents/$uuid"
        }
        return s3.listObjectsV2(request).contents
    }

with this factory

import aws.sdk.kotlin.services.s3.S3Client
import io.micronaut.context.annotation.Factory
import io.micronaut.context.annotation.Property
import jakarta.inject.Singleton

@Factory
class S3Factory {
    @Singleton
    fun getS3Client(): S3Client = S3Client {
        region = "eu-central-1"
    }
}

the resulting exception

15:41:51.721 [DefaultDispatcher-worker-17] ERROR i.m.http.server.RouteExecutor - Unexpected error occurred: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
aws.smithy.kotlin.runtime.http.HttpException: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
        at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine.roundTrip(OkHttpEngine.kt:158)
        at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine$roundTrip$1.invokeSuspend(OkHttpEngine.kt)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Caused by: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
        at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:209)
        at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:111)
        at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:65)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at aws.smithy.kotlin.runtime.http.engine.okhttp.MetricsInterceptor.intercept(MetricsInterceptor.kt:30)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:205)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:537)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.EOFException: \n not found: limit=0 content=
        at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:335)
        at okhttp3.internal.http1.HeadersReader.readLine(HeadersReader.kt:29)
        at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:179)
        ... 18 common frames omitted

Expected behavior

Not failing randomly exactly 5 times when this error occurs.

Current behavior

Like explained before the error which is thrown.

15:41:51.721 [DefaultDispatcher-worker-17] ERROR i.m.http.server.RouteExecutor - Unexpected error occurred: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
aws.smithy.kotlin.runtime.http.HttpException: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
        at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine.roundTrip(OkHttpEngine.kt:158)
        at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine$roundTrip$1.invokeSuspend(OkHttpEngine.kt)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Caused by: java.io.IOException: unexpected end of stream on https://example-bucket.s3.eu-central-1.amazonaws.com/...
        at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:209)
        at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:111)
        at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:65)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at aws.smithy.kotlin.runtime.http.engine.okhttp.MetricsInterceptor.intercept(MetricsInterceptor.kt:30)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:205)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:537)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.EOFException: \n not found: limit=0 content=
        at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:335)
        at okhttp3.internal.http1.HeadersReader.readLine(HeadersReader.kt:29)
        at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:179)
        ... 18 common frames omitted

Here with more attempts set going trough

09:29:19.565 [default-nioEventLoopGroup-1-3] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(i
d=aws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.566 [default-nioEventLoopGroup-1-3] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: 004111cbb877796271fe307182ce84a0aa2ce6414c9a1e5a74ba3cd038d64e0b
09:29:19.574 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.h.middleware.RetryMiddleware - retrying request, attempt 2
09:29:19.574 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(id=a
ws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.574 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: 8bc5844c65f86333f4cb21e7206b3ae7e471c8973789db9f86605d02ddc5f0a4
09:29:19.588 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.h.middleware.RetryMiddleware - retrying request, attempt 3
09:29:19.588 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(id=a
ws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.588 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: 9d2db5c865b79490bb54de1f21d43909e23a0ab9611ebd4f488ad00af09c8f56
09:29:19.609 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.h.middleware.RetryMiddleware - retrying request, attempt 4
09:29:19.609 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(id=a
ws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.609 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: 74a7dffb53a0ab23be7e32814c42dbe526e96b768e71ba406e13b4a374bb3814
09:29:19.621 [DefaultDispatcher-worker-18] DEBUG a.s.k.r.h.middleware.RetryMiddleware - retrying request, attempt 5
09:29:19.621 [DefaultDispatcher-worker-18] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(id=
aws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.621 [DefaultDispatcher-worker-18] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: 549aae8fd9ed87f1ffdd3117dbfcf69b9522946925a2a97356a31daac8b58aa0
09:29:19.653 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.h.middleware.RetryMiddleware - retrying request, attempt 6
09:29:19.653 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.http.operation.AuthHandler - resolved endpoint: Endpoint(uri=https://example-bucket.s3.eu-central-1.amazonaws.com, headers=null, attributes={AttributeKey(aws.smithy.kotlin#endpointAuthSchemes)=[AuthOptionImpl(schemeId=AuthSchemeId(id=a
ws.auth#sigv4), attributes={AttributeKey(aws.smithy.kotlin.signing#AwsSigningRegion)=eu-central-1, AttributeKey(aws.smithy.kotlin.signing#AwsSigningService)=s3, AttributeKey(aws.smithy.kotlin.signing#UseDoubleUriEncode)=false})]})
09:29:19.653 [DefaultDispatcher-worker-2] DEBUG a.s.k.r.a.a.DefaultAwsSignerImpl - Calculated signature: c1e9643a2ffa94e87ad7d1828c7aaf215374963703785314552aefceb0a4c357
09:29:19.832 [DefaultDispatcher-worker-18] DEBUG httpTraceMiddleware - HttpResponse: 200: OK

Steps to Reproduce

The framework in use is Micronaut in the version 4.2.2 . The s3 bucket itself has several objects in it and returns with the prefix key 10 elements.

The code was started locally via Gradle (version 8.4) and invoked over the micronaut controoler via Postman. Note that the same behavior is present in the cloud environment.

import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.ListObjectsV2Request
import jakarta.inject.Singleton
import io.micronaut.context.annotation.Property


@Singleton
class Service(private val s3: S3Client) : Logger {
    @Property(name = "bucket-name")
    private lateinit var awsbucket: String

    suspend fun listObjects(uuid: UUID): List<Object>? {
        val request = ListObjectsV2Request {
            bucket = awsbucket
            prefix = "documents/$uuid"
        }
        return s3.listObjectsV2(request).contents
    }

with this factory

import aws.sdk.kotlin.services.s3.S3Client
import io.micronaut.context.annotation.Factory
import io.micronaut.context.annotation.Property
import jakarta.inject.Singleton

@Factory
class S3Factory {
    @Singleton
    fun getS3Client(): S3Client = S3Client {
        region = "eu-central-1"
    }
}

with these build.gradle.kts file

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.9.22"
    id("org.jetbrains.kotlin.plugin.allopen") version "1.9.22"
    id("com.google.devtools.ksp") version "1.9.22-1.0.17"
    id("com.github.johnrengelman.shadow") version "8.1.1"
    id("io.micronaut.application") version "4.3.2"
    id("io.micronaut.aot") version "4.3.2"
}

version = "0.1"
group = "com.example"

val kotlinVersion="1.9.22"
repositories {
    mavenCentral()
}

dependencies {
    ksp("io.micronaut:micronaut-http-validation")
    ksp("io.micronaut.serde:micronaut-serde-processor")
    implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")
    implementation("io.micronaut.serde:micronaut-serde-jackson")
    implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
    compileOnly("io.micronaut:micronaut-http-client")
    runtimeOnly("ch.qos.logback:logback-classic")
    runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin")
    testImplementation("io.micronaut:micronaut-http-client")
    implementation("aws.sdk.kotlin:s3:1.0.54")

}


application {
    mainClass.set("com.example.ApplicationKt")
}
java {
    sourceCompatibility = JavaVersion.toVersion("21")
}


graalvmNative.toolchainDetection.set(false)
micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("com.example.*")
    }
    aot {
    // Please review carefully the optimizations enabled below
    // Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details
        optimizeServiceLoading.set(false)
        convertYamlToJava.set(false)
        precomputeOperations.set(true)
        cacheEnvironment.set(true)
        optimizeClassLoading.set(true)
        deduceEnvironment.set(true)
        optimizeNetty.set(true)
    }
}

Possible Solution

No response

Context

I want to show the user the s3 objects which the user has saved in the cloud via a web app. However at some point the request fails randomly (locally and in the cloud).

AWS Kotlin SDK version used

1.0.54

Platform (JVM/JS/Native)

Java 21.0.2 with gradle 8.4

Operating System and version

Windows 10 Pro

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.p2This is a standard priority issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions