Creating a custom 'EventStoreProvider' implementation with order() < 0 results in a NPE
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
core
Describe the bug
The guide for selecting a default provider for an SPI states (point 2):
The provider with the highest order (providers with order ⇐ 0 are ignored)
https://www.keycloak.org/server/configuration-provider#_configuring_a_default_provider_for_an_spi
I built an extension: a custom EventStoreProvider (id ext-mongo). The goal is for the built-in jpa provider to remain the default events store, and for my provider to be used only when it is explicitly selected, e.g. KC_SPI_EVENTS_STORE__PROVIDER=ext-mongo (--spi-events-store--provider=ext-mongo).
Following the documented rule, I gave my factory a non-positive order so it would be "ignored" for default selection and not disturb the existing default:
@Override
public int order() {
return -1;
}Based on the wording "providers with order ⇐ 0 are ignored", I expected my provider to simply not participate in default selection, leaving jpa as the default. Instead, as soon as my provider is registered (and no explicit spi-events-store-provider is set), the SPI ends up with no default provider, and the events endpoint throws an uncaught NPE:
java.lang.NullPointerException: Cannot invoke "org.keycloak.events.EventStoreProvider.createQuery()" because "eventStore" is null
at org.keycloak.services.resources.admin.RealmAdminResource.getEvents(RealmAdminResource.java:907)So the provider with order() <= 0 is ignored exactly as documented — but "ignored" should not also mean "removes the built-in default and leaves the SPI with none." And regardless of the resolution outcome, a null default should not surface as an uncaught NPE on a REST endpoint.
Version
26.6.2
Regression
- The issue is a regression
Expected behavior
A registered factory with order() <= 0 is truly ignored, so the remaining qualifying built-in (jpa) stays the default. This matches the documented wording and lets an extension ship as opt-in-only — selectable by id via spi-events-store-provider, without becoming or breaking the default.
There should be a supported way to deploy an additional EventStoreProvider that does not become the default and does not disturb the built-in jpa default, used only when explicitly selected.
Actual behavior
Registering a second EventStoreProvider factory with order() <= 0 and no explicit spi-events-store-provider leaves the SPI with no default provider.
GET /admin/realms/{realm}/events (and the Admin Console Events view) throws an uncaught NullPointerException because session.getProvider(EventStoreProvider.class) is null.
How to Reproduce?
- Implement a custom
EventStoreProviderFactory(idext-mongo), registered via@AutoService/META-INF/services, withorder()returning-1. - Build the jar, place it in
providers/, and start Keycloak without settingspi-events-store-provider/KC_SPI_EVENTS_STORE__PROVIDER. 3 .Open the realm's Events view in the Admin Console. - Observe the 500 /
NullPointerExceptionabove.
Expected: the built-in jpa store is used and events load, since the custom provider declared order() <= 0 and should be ignored.
Anything else?
No response
Source: keycloak/keycloak