使用Java Discord API转发私信至频道时发送图片报错的解决方法
Fix "Cannot build an empty message" When Forwarding Private Messages with Images to Discord Channel
Problem Cause
This exception pops up when a user sends a private message with only an image (no text, embeds, or interactive components). Even though the original message has an attachment, MessageCreateData.fromMessage(event.getMessage()) fails to properly handle the attachment during message construction. Discord requires attachments to be re-uploaded when forwarding (since their original URLs are temporary), and without this step, the built message ends up empty—triggering the error.
Solution
We need two key fixes:
- Skip completely empty messages to avoid the exception in the first place.
- Properly re-upload attachments when forwarding messages that contain them.
Here's the revised code for your PrivateMessage class:
public class PrivateMessage extends ListenerAdapter { private TextChannel channel; @Override public void onReady(@NotNull ReadyEvent event) { channel = event.getJDA().getChannelById(TextChannel.class, 962688156942073887L); } @Override public void onMessageReceived(@NotNull MessageReceivedEvent event) { // Only process private messages if (!event.isFromType(ChannelType.PRIVATE)) { return; } Message privateMsg = event.getMessage(); // Skip messages with no valid content at all if (privateMsg.getContentRaw().isEmpty() && privateMsg.getEmbeds().isEmpty() && privateMsg.getComponents().isEmpty() && privateMsg.getAttachments().isEmpty()) { return; } // Start building the message from the private message content MessageCreateDataBuilder msgBuilder = MessageCreateData.fromMessage(privateMsg).toBuilder(); // Handle attachments: re-upload them since Discord's attachment URLs are temporary List<MessageAttachment> attachments = privateMsg.getAttachments(); if (!attachments.isEmpty()) { for (MessageAttachment attachment : attachments) { // Asynchronously download the attachment to avoid blocking the bot attachment.getProxy().download().thenAccept(inputStream -> { msgBuilder.addFiles(Attachment.fromData(inputStream, attachment.getFileName())); channel.sendMessage(msgBuilder.build()).queue(); }).exceptionally(throwable -> { // Log errors and notify the channel if attachment forwarding fails throwable.printStackTrace(); channel.sendMessage("Failed to forward attachment: " + throwable.getMessage()).queue(); return null; }); } } else { // No attachments? Send the message directly channel.sendMessage(msgBuilder.build()).queue(); } } }
Key Changes Explained
- Empty Message Guard: We first check if the private message has no content of any type (text, embeds, components, attachments). If so, we skip forwarding it to avoid the
IllegalStateException. - Attachment Re-Upload: Since Discord's attachment URLs are short-lived, we download each attachment and re-add it to the message builder before sending. This ensures the image is properly uploaded to the target channel.
- Asynchronous Error Handling: We use non-blocking async calls to download attachments, paired with error handling to notify the channel if an attachment fails to forward.
内容的提问来源于stack exchange,提问作者Alex Cai
相关产品推荐
相关产品推荐

