question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JDA throws random stream closed IOException

See original GitHub issue

General Troubleshooting

  • I have checked for similar issues on the Issue-tracker.
  • I have updated to the latest JDA version
  • I have checked the branches or the maintainers’ PRs for upcoming bug fixes.

Expected Behaviour

I’ve been trying to resolve this problem for days now, I looked Stackoverflow, pull requests, issue reports, but couldn’t get quite satisfied answer from them. So I built a bot which provides information about one mobile game.

For some commands, it needs to generate image files to improve visuals. Since these generated files don’t need to be cached or stored, meaning that they are just temporary files, I delete them whenever bot could send message successfully. Now problem here appears, I really can’t give good example to reproduce this, but when it gets rate-limited by Discord, if message sent contains file, JDA randomly throws IOException with stream closed error.

I can’t get exact way to reproduce this problem, stack trace gives me something related with RateLimiter, so excuse me that above statements are purely guessing, and my lack of deep knowledge about JDA structure or Discord data… Code example below is one of basic format that I use in my codes; I send message (sendMessage) with file (addFile), and call queue() message. Since queue message can provide listener for when message successfully got sent, or failed to, I add file deletion methods in there, so that bot can delete temporary files only when message sending task is fully done.

This error happens also when I obtain Message instance by calling complete() as well. I thought it could be problem related with these temporary files, so I made bot delete them with 5 seconds delay. It could be just that 5 seconds weren’t enough, but such delayed deletion couldn’t solve problem.

My bot is open source

Adapter that I implemented is here One of command which caused this problem is here or here from line 225

I… can’t suggest or provide what should happen because I actually don’t know if I’m using API incorrectly, but I can guess that such problem shouldn’t be appeared, or handled by JDA API itself. I will wait for answer, thanks for reading these

Code Example for Reproduction Steps

//Use this method in "onMessageReceived" for "ListnerAdapter" class
public void tryToReplicate(GenericMessageEvent event) {
    MessageChannel ch = event.getChannel();

    //This is merely example
    //My actual code doesn't spam command like this, this is just for trying to replicate problem
    //Basically spamming message with file to trigger rate-limit
    for(int i = 0; i < 20; i++) {
        File f = generateFile(); //Generate any temporary file

        ch.sendMessage("File")
            .addFile(f, "Example.txt")
            .queue(m -> {
                if(f.exist() && !f.delete()) {
                    System.out.println("failed to delete file : "+f.getAbsolutePath());
                }
            }, e -> {
                e.printStackTrace();

                if(f.exist() && !f.delete()) {
                    System.out.println("failed to delete file : "+f.getAbsolutePath());
                }
            });
    }
}

Code for JDABuilder or DefaultShardManagerBuilder used

JDABuilder builder = JDABuilder.createDefault(TOKEN);

builder.setEnabledIntents(
        GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_EMOJIS, GatewayIntent.GUILD_MESSAGES, 
        GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.DIRECT_MESSAGES, GatewayIntent.DIRECT_MESSAGE_REACTIONS
);
builder.disableCache(CacheFlag.VOICE_STATE);
builder.setActivity(Activity.playing(develop ? dev : normal));
builder.addEventListeners(new AllEventAdapter());

JDA client = builder.build();

//Check my github source link below, line 48 for detailed further codes
//https://github.com/battlecatsultimate/PackPack/blob/main/src/main/java/mandarin/packpack/PackBot.java

Exception or Error

net.dv8tion.jda.api.exceptions.ErrorResponseException: -1: java.io.IOException
	at net.dv8tion.jda.api.exceptions.ErrorResponseException.create(ErrorResponseException.java:185)
	at net.dv8tion.jda.api.requests.Request.onFailure(Request.java:117)
	at net.dv8tion.jda.internal.requests.RestActionImpl.handleResponse(RestActionImpl.java:273)
	at net.dv8tion.jda.api.requests.Request.handleResponse(Request.java:259)
	at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:255)
	at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:142)
	at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:125)
	at net.dv8tion.jda.internal.requests.ratelimit.BotRateLimiter$Bucket.run(BotRateLimiter.java:481)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.io.IOException: Stream Closed
	at java.base/java.io.FileInputStream.readBytes(Native Method)
	at java.base/java.io.FileInputStream.read(FileInputStream.java:273)
	at okio.InputStreamSource.read(JvmOkio.kt:90)
	at okio.Buffer.writeAll(Buffer.kt:1642)
	at okio.RealBufferedSource.readByteArray(RealBufferedSource.kt:236)
	at net.dv8tion.jda.internal.utils.BufferedRequestBody.writeTo(BufferedRequestBody.java:60)
	at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.kt:157)
	at okhttp3.MultipartBody.writeTo(MultipartBody.kt:93)
	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:59)
	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:83)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
	at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
	at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:202)
	... 9 more
Caused by: net.dv8tion.jda.api.exceptions.ContextException
	at net.dv8tion.jda.api.exceptions.ContextException.here(ContextException.java:54)
	at net.dv8tion.jda.api.requests.Request.<init>(Request.java:71)
	at net.dv8tion.jda.internal.requests.RestActionImpl.queue(RestActionImpl.java:198)
	at mandarin.packpack.commands.data.StageImage.handleLast(StageImage.java:126)
	at mandarin.packpack.commands.data.StageImage.doSomething(StageImage.java:83)
	at mandarin.packpack.commands.ConstraintCommand.lambda$execute$1(ConstraintCommand.java:129)
	... 1 more

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
MinnDevelopmentcommented, Jul 9, 2022

I think this is the bug that was fixed here. We used to close the stream too early in an older version, this shouldn’t be happening anymore on the current release.

0reactions
MinnDevelopmentcommented, Jul 9, 2022

I know Files.createTempFile() method, but I need to store files in this temp folder

The method I linked lets you specify a directory as the first parameter, that should work. Files.createTempFile(Paths.get("./temp"), "image", ".png")

Which creates a file like this:

jshell> Files.createTempFile(Paths.get("./temp"), "image", ".png")
$1 ==> ./temp/image6700668970453732818.png
Read more comments on GitHub >

github_iconTop Results From Across the Web

java IO Exception: Stream Closed - Stack Overflow
The first line of your stack trace says it all: java.io.IOException: Stream closed . You can't close it and then write to it...
Read more >
IOException - Stream closed — oracle-tech
My code runs well when I am using eclipse but when i create a jar and run, it shows the error as below....
Read more >
"Stream has already been operated upon or closed" Exception ...
A Stream implementation may throw IllegalStateException if it detects that the Stream is being reused. Whenever a terminal operation is called ...
Read more >
Random "Stream closed" exception when using basicBuilder ...
I'm using JUnit with JMH benchmarks, TestContainers and jersey-client to test some application. When JMH the benchmark uses hundreds of ...
Read more >
java.lang.InternalError: java.io.IOException: Stream closed
SEVERE: Servlet.service() for servlet jasperserver threw exception java.lang.InternalError: java.io.IOException: Stream closed at java.text.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found