JDA throws random stream closed IOException
See original GitHub issueGeneral 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:
- Created a year ago
- Comments:8 (1 by maintainers)
Top GitHub Comments
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.
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: