aeron-io/aeron · error · ArchiveException

authorisation service cannot be null

Error message

authorisation service cannot be null

What it means

ArchiveConductor obtains the AuthorisationService via ctx.authorisationServiceSupplier().get() at startup. A null service is rejected with ArchiveException because every archive request must be checked against a service; use a permissive service when authorisation is not needed.

Solutions

  1. Fix the authorisationServiceSupplier to return a non-null AuthorisationService.
  2. Supply a permissive AuthorisationService that always returns true for isAuthorised when access control is not required.
  3. Verify the DI/supplier wiring so the intended service bean is actually constructed.

Example fix

// before
ctx.authorisationServiceSupplier(() -> null);
// after
ctx.authorisationServiceSupplier(() -> (protocolId, actionId, ctx) -> true); // allow-all service
Defensive patterns

Strategy: validation

Validate before calling

AuthorisationService s = ctx.authorisationServiceSupplier().get();
if (s == null)
{
    throw new IllegalStateException("authorisationServiceSupplier must return a non-null service");
}

Prevention

When it happens

Trigger: Launching Archive with an authorisationServiceSupplier whose get() returns null, e.g. an unconfigured DI provider or a custom lambda returning null.

Common situations: Applications wiring authentication but forgetting authorisation; custom supplier factories that return null when no service class is configured.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/d9ecf926fce364f0. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/ArchiveConductor.java:218

        connectTimeoutMs = TimeUnit.NANOSECONDS.toMillis(ctx.connectTimeoutNs());
        sessionLivenessCheckIntervalMs = TimeUnit.NANOSECONDS.toMillis(ctx.sessionLivenessCheckIntervalNs());
        catalog = ctx.catalog();
        markFile = ctx.archiveMarkFile();
        dutyCycleTracker = ctx.conductorDutyCycleTracker();
        cachedEpochClock.update(epochClock.time());

        random = ctx.secureRandom();

        authenticator = ctx.authenticatorSupplier().get();
        if (null == authenticator)
        {
            throw new ArchiveException("authenticator cannot be null");
        }

        authorisationService = ctx.authorisationServiceSupplier().get();
        if (null == authorisationService)
        {
            throw new ArchiveException("authorisation service cannot be null");
        }

        unavailableCounterHandlerRegistrationId = aeron.addUnavailableCounterHandler(this);
        closeHandlerRegistrationId = aeron.addCloseHandler(this::abort);

        recordingEventsProxy = ctx.recordingEventsEnabled() ? new RecordingEventsProxy(
            aeron.addExclusivePublication(ctx.recordingEventsChannel(), ctx.recordingEventsStreamId())) : null;

        if (ctx.controlChannelEnabled())
        {
            final ChannelUri controlChannelUri = ChannelUri.parse(ctx.controlChannel());
            controlChannelUri.put(CommonContext.SPARSE_PARAM_NAME, Boolean.toString(ctx.controlTermBufferSparse()));
            controlSubscription = addSubscriptionWithRetry(
                aeron, ctx.idleStrategy(), controlChannelUri.toString(), ctx.controlStreamId(), this);
        }
        else
        {
            controlSubscription = null;

View on GitHub (pinned to 6d60124e15)