Releases: discord-jda/JDA
v6.0.0-rc.2 | New Pin Pagination API
Overview
This release includes a minor breaking change to the retrievePinnedMessages
method.
Originally, this method could only fetch up to 50 pinned messages. However, the underlying endpoint has been deprecated and replaced with a new paginated endpoint, as detailed in the Discord Changelog.
We have updated our API to utilize a PaginationAction
. The callback response is now a list of PinnedMessage
objects instead of a list of messages. Each PinnedMessage
instance contains the timestamp when the message was pinned and the pinned message object. With this pagination action, the retrieval of pinned messages is no longer limited to 50 messages and can now fetch more, for instance by using takeAsync(200)
.
To replicate the previous behavior (retrieving only up to 50 pinned messages), you can use queue()
as before, but you will need to map the list to a List<Message>
as follows:
channel.retrievePinnedMessages()
.map(list -> list.stream().map(PinnedMessage::getMessage).toList())
.queue(list -> ...);
Changes
- Make JDA#getMutualGuilds accept UserSnowflake instead of User objects by @MineKing9534 in #2877
- Add new pinned message pagination by @MinnDevelopment in #2874
Full Changelog: v6.0.0-rc.1...v6.0.0-rc.2
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:6.0.0-rc.2")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>6.0.0-rc.2</version>
</dependency>
v6.0.0-rc.1 | New Components
Overview
Warning
This is the first release candidate for JDA 6.0.0. The major version bump reflects several breaking changes to the message and modal component APIs. Additional breaking changes may still be introduced before the final stable release of 6.0.0.
This version introduces support for Components Version 2, a significant update to Discord's component system. To accommodate this new API, we’ve made a number of key changes to our component implementation:
-
All components are now immutable
Previously,ActionRow
allowed modification of its contained components. To simplify and modernize the API, this mutability has been removed. -
New top-level component interfaces
TheLayoutComponent
interface (previously only implemented byActionRow
) has been replaced by two new interfaces:
-MessageTopLevelComponent
-ModalTopLevelComponent
This change reflects the increased flexibility introduced in Components V2, where top-level components are no longer restricted to layout containers likeActionRow
. Components such asTextDisplay
andFileDisplay
can now appear directly at the top level. -
Renamed
getId
→getCustomId
The originalgetId
method has been renamed togetCustomId
to avoid confusion with Discord's newgetUniqueId
, which is a numeric, auto-generated identifier. -
Temporary removal of
toData
for components
Some components now require attachments to function properly, complicating serialization. We’ve removed thetoData
method for now and are working on a new, more capable serialization API that will be introduced in a later update.
Big thanks to @freya022 and @DV8FromTheWorld for contributing on this giant feature!
Using Components V2
To use the new components introduced in this release, you must enable the Components V2 feature flag on your message request. This can be done using the useComponentsV2
method on MessageRequest
.
Tip
Enabling this flag comes with certain limitations, so we strongly recommend reviewing the documentation for important details before integrating it into your project.
To get started, check out the new ComponentsV2Example to explore the possibilities of this updated API. You can also see it in action in a demo project by @DV8FromTheWorld: discord-pokedex.

New Components
JDA 6 introduces several new component types as part of the Components V2 system:
-
Container
Displays components inside a visually distinct box — similar to how embeds are styled. -
Thumbnail
Shows a small image next to text. Commonly used as an accessory within aSection
component. -
FileDisplay
Displays a file attachment as a downloadable item. For visual file content (e.g., images), consider usingMediaGallery
instead. -
MediaGallery
Shows multiple images in a gallery layout — similar to a list of image attachments in Discord. -
Section
Displays a block of text content with optional accessories like thumbnails or buttons. -
Separator
Adds vertical spacing between components, helping visually organize content. -
TextDisplay
A simple text component used to display content without relying on thecontent
field of a message.
Note
Components that use files, such as FileDisplay
or MediaGallery
, will automatically attach files as message attachments in your requests.
New Utilities For Components
Several new utilities have been added to simplify working with complex component structures — including traversal, replacement, and deserialization:
-
MessageComponentTree
&ModalComponentTree
A single object that provides the functionality to iterate and replace components easily. -
ComponentReplacer
An interface for removing or replacing components within a tree or collection.
For example, remove a component by unique ID usingbyUniqueId(1, null)
. -
ComponentIterator
&ComponentPathIterator
Tools for recursively iterating through nested components, including child elements like buttons within anActionRow
. -
Components
A utility class used for parsing serialized JSON into JDA's component model.
Migrating To 6.0.0
To help ease the upgrade to JDA 6.0.0, we've provided an OpenRewrite recipe that can automatically refactor parts of your codebase. This will update imports and replace a few method calls with their new equivalents in JDA 6.0.0.
However, not all breaking changes can be handled automatically — for example, code that relied on the mutability of ActionRow
will require manual adjustments.
The OpenRewrite Recipe
Before applying the recipe, make sure you’re using version control (e.g., Git) or back up your project manually. You’ll also need to be using Gradle or Maven to apply the migration.
Gradle
We are using the OpenRewrite Gradle Plugin. Before changing your JDA version in gradle, you can add the rewrite plugin and use the recipe to migrate your code:
plugins {
id("org.openrewrite.rewrite") version "7.11.0"
}
repositories {
mavenCentral()
}
dependencies {
// Your current JDA version before upgrading to 6.0.0
implementation("net.dv8tion:JDA:5.+")
// The current 6.0.0 release version
rewrite("net.dv8tion:JDA:6.0.0-rc.1")
rewrite("org.openrewrite.recipe:rewrite-java-dependencies:1.37.0")
}
rewrite {
activeRecipe("net.dv8tion.MigrateComponentsV2")
}
Once you configured this plugin, you can use the rewriteDryRun
task to generate a git patch in build/reports/rewrite/rewrite.patch
to see what the plugin will do with your source code. To apply the changes, either use this patch or use rewriteRun
.
After migrating your code, you can then update your JDA version (if the rewrite hasn't done it already) and remove the plugin again.
Maven
We are using the OpenRewrite Maven Plugin. Before changing your JDA version in your pom, you can add the rewrite plugin and use the recipe to migrate your code:
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>6.13.0</version>
<configuration>
<activeRecipes>
<recipe>net.dv8tion.MigrateComponentsV2</recipe>
</activeRecipes>
</configuration>
<dependencies>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-java-dependencies</artifactId>
<version>1.37.0</version>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>6.0.0-rc.1</version>
</dependency>
</dependencies>
</plugin>
Once you configured this plugin, you can use the rewrite:dryRun
task to generate a git patch in target/site/rewrite/rewrite.patch
to see what the plugin will do with your source code. To apply the changes, either use this patch or use rewrite:run
.
After migrating your code, you can then update your JDA version (if the rewrite hasn't done it already) and remove the plugin again.
The ComponentReplacer
If you previously used LayoutComponent.updateComponents
or changed an action row with the mutable getComponents()
, you will have to migrate your code to the new ComponentReplacer instead.
Before:
List<LayoutComponent> components = message.getComponents();
LayoutComponent.updateComponent(
components,
"my-component-id",
Button.primary("button-id", "Click me").asDisabled()
);
After:
MessageComponentTree components = message.getComponentTree();
...
v5.6.1
Bug Fixes
- Remove check for isWebhookMessage in checkUser by @MinnDevelopment in #2857
Full Changelog: v5.6.0...v5.6.1
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.6.1")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.6.1</version>
</dependency>
v5.6.0 | ApplicationManager and minor improvements
Overview
This release introduces the ApplicationManager, which can be used to update the application's description and other settings through JDA.
New Features
- Implement application manager by @MinnDevelopment and @raul1ro in #2854
- Require a
UserSnowflake
inmoveVoiceMember
andkickVoiceMember
by @freya022 in #2852
Changes
- Add
with_components=true
query param to WebhookClient requests by @Xirado in #2850 - Set thread ID when manipulating message objects made by webhooks by @freya022 in #2849
Bug Fixes
- Fix message content intent warning being logged when accessing messag… by @Xirado in #2851
- Handle new voice websocket close codes by @MinnDevelopment in #2855
Full Changelog: v5.5.1...v5.6.0
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.6.0")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.6.0</version>
</dependency>
v5.5.1 | Bug fixes and performance improvements
Overview
This is a small release, including a bug fix for editCommand
and editCommandById
, as well as some performance improvements for looking up members by roles.
Additionally, you can now create threads with a custom slowmode.
New Features
- Add
AbstractThreadCreateAction#setSlowmode
by @replaceitem in #2842 - Add Member#getUnsortedRoles by @MinnDevelopment in #2841
Bug Fixes
- Fix editCommandById by @MinnDevelopment in #2839
Full Changelog: v5.5.0...v5.5.1
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.5.1")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.5.1</version>
</dependency>
v5.5.0 | Improved voice state cache and file proxies
Changes to voice state cache (#2835)
Voice states are now cached independently of guild members. JDA can now detect when a member connects or disconnects from an audio channel, even when the member is not currently cached.
With this change, you can technically use MemberCachePolicy.NONE
and will still receive voice join / leave events, as long as CacheFlag.VOICE_STATE
is enabled.
To reduce the memory footprint, we now only cache voice states if the member is connected to an audio channel. While disconnected, we will not keep the voice state cached, meaning we lose track of muted/deafend state and return an "empty" voice state for Member#getVoiceState
.
Improvements to FileProxy (#2782 and #2727)
The FileProxy, ImageProxy, and AttachmentProxy now all support downloadAsFileUpload to easily stream a Discord proxies URL to a message.
@Override
public void onMessageReceived(MessageReceivedEvent event) {
List<Message.Attachment> attachments = event.getMessage().getAttachments();
List<FileUpload> uploads = attachments.stream()
.map(attachment ->
attachment
.getProxy()
.downloadAsFileUpload(attachment.getWidth(), attachment.getHeight()))
.collect(Collectors.toList());
event.getChannel().sendFiles(uploads).queue();
}
New Features
- Add
downloadAsFileUpload
to file proxies by @freya022 in #2782 - Add
ImageProxy#downloadAsIcon
by @freya022 in #2727
Changes
- Move voice state cache to guild by @MinnDevelopment in #2835
Bug Fixes
- Allow \ in invite links by @rtm516 in #2796
- Fix checks in CommandEditAction by @MinnDevelopment in #2837
Full Changelog: v5.4.0...v5.5.0
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.5.0")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.5.0</version>
</dependency>
v5.4.0 | Interaction callback response and security incidents
Access the created or updated message from interaction replies (#2798)
You can now use InteractionHook#getCallbackResponse to access the messages created by interaction replies.
@Override
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
event.reply("React with your favorite emoji")
.map(hook -> hook.getCallbackResponse().getMessage())
.flatMap(message -> message.addReaction(emoji))
.queue();
}
Previously, this could be done using an additional retrieveOriginal
request. To reduce requests and improve responsiveness, we recommend preferring this new getter instead.
Guild security incidents (#2577)
With guild security incidents, you can now be aware when Discord detects raids or spam in direct messages in a guild. These detections are available with Guild#getSecurityIncidentDetections and are updated with GuildUpdateSecurityIncidentDetectionsEvent.
Additionally, you can modify the security incident actions to temporarily pause invites or disable direct messages in your guild. See Guild#modifySecurityIncidents for details.
guild.modifySecurityIncidents(SecurityIncidentActions.enabled(
// Pause invites for 2 hours
OffsetDateTime.now().plusHours(2),
// Disable direct messages for 1 hour
OffsetDateTime.now().plusHours(1)
)).queue();
// Or disable security incident actions prematurely
guild.modifySecurityIncidents(SecurityIncidentActions.disabled()).queue();
New Features
- Add interaction callback response handling by @Xirado in #2798
- Add support for guild security incidents by @MinnDevelopment in #2577
- Add a way to retrieve users that used super reaction by @MTM123 in #2786
- Add Guild#retrieveScheduledEvents by @senseiwells in #2800
Changes
Bug Fixes
- Prevent firing voice state update events if member is not cached by @freya022 in #2773
- Fix
FileProxy#withClient
return types by @freya022 in #2698
Full Changelog: v5.3.2...v5.4.0
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.4.0")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.4.0</version>
</dependency>
v5.3.2 | Bug fix for PrivateChannel#getName
Overview
Small bug fix release.
Bug Fixes
Full Changelog: v5.3.1...v5.3.2
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.3.2")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.3.2</version>
</dependency>
v5.3.1 | Bug fixes
Overview
Small bug fix release due to API changes regarding user-installed applications.
Bug Fixes
Full Changelog: v5.3.0...v5.3.1
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.3.1")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.3.1</version>
</dependency>
v5.3.0 | User-Installable Apps
Overview
After many months of waiting, this release finally adds support for user-installable apps. This will allow you to make use of interactions (and especially commands) anywhere on Discord, by installing the application on a user directly instead of a guild.
Creating User-Installable Apps
To create a user-installable app, you first have to enable the feature in your application dashboard in the installation settings:
Once enabled, you can create user-installable commands, by changing the integration types:
Commands.slash("say", "Makes the bot say what you tell it to")
// Allow the command to be used anywhere (Bot DMs, Guild, Friend DMs, Group DMs)
.setContexts(InteractionContextType.ALL)
// Allow the command to be installed on users instead of guilds
.setIntegrationTypes(IntegrationType.USER_INSTALL)
.addOption(STRING, "content", "What the bot should say", true)
Installing to a User
To actually install your app to a user, you can use the generator provided by discord. In the OAuth2 URL Generator, change the integration type to User Install:
The generated link, can now be used to install your application to the authorizing user.
Detached Guilds / Roles / Channels / Members
This comes with a few changes to expectations around JDA functionality. Since interactions can now come from anywhere on Discord, some features aren't available in certain contexts.
Some entities can now appear as Detachable Entity, which essentially means that they come from a guild or private channel, that your bot is not directly involved in.
For instance, if a command is installed on a user and that command is used in a guild, your bot is not necessarily a member of that guild. Since the bot is not a member, it only has access to the guild context, that the interaction event provides. Many features such as channels, roles, or members are not accessible without being an actual member of the guild. If you try to use or access anything that isn't accessible, JDA will throw a new DetachedEntityException.
New Features
- Add
Guild#retrieveMemberVoiceState
by @PascalNB in #2729 - Add support for user-installable apps by @freya022 in #2633
Full Changelog: v5.2.3...v5.3.0
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("net.dv8tion:JDA:5.3.0")
}
Maven
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.3.0</version>
</dependency>