{"record":{"id":"67d30c54f2c63a6f","repo":"aeron-io/aeron","slug":"authenticator-cannot-be-null","errorCode":null,"errorMessage":"authenticator cannot be null","messagePattern":"authenticator cannot be null","errorType":"exception","errorClass":"ArchiveException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/ArchiveConductor.java","lineNumber":212,"sourceCode":"        aeron = ctx.aeron();\n        aeronAgentInvoker = aeron.conductorAgentInvoker();\n        driverAgentInvoker = ctx.mediaDriverAgentInvoker();\n        epochClock = ctx.epochClock();\n        nanoClock = ctx.nanoClock();\n        archiveDir = ctx.archiveDir();\n        connectTimeoutMs = TimeUnit.NANOSECONDS.toMillis(ctx.connectTimeoutNs());\n        sessionLivenessCheckIntervalMs = TimeUnit.NANOSECONDS.toMillis(ctx.sessionLivenessCheckIntervalNs());\n        catalog = ctx.catalog();\n        markFile = ctx.archiveMarkFile();\n        dutyCycleTracker = ctx.conductorDutyCycleTracker();\n        cachedEpochClock.update(epochClock.time());\n\n        random = ctx.secureRandom();\n\n        authenticator = ctx.authenticatorSupplier().get();\n        if (null == authenticator)\n        {\n            throw new ArchiveException(\"authenticator cannot be null\");\n        }\n\n        authorisationService = ctx.authorisationServiceSupplier().get();\n        if (null == authorisationService)\n        {\n            throw new ArchiveException(\"authorisation service cannot be null\");\n        }\n\n        unavailableCounterHandlerRegistrationId = aeron.addUnavailableCounterHandler(this);\n        closeHandlerRegistrationId = aeron.addCloseHandler(this::abort);\n\n        recordingEventsProxy = ctx.recordingEventsEnabled() ? new RecordingEventsProxy(\n            aeron.addExclusivePublication(ctx.recordingEventsChannel(), ctx.recordingEventsStreamId())) : null;\n\n        if (ctx.controlChannelEnabled())\n        {\n            final ChannelUri controlChannelUri = ChannelUri.parse(ctx.controlChannel());\n            controlChannelUri.put(CommonContext.SPARSE_PARAM_NAME, Boolean.toString(ctx.controlTermBufferSparse()));","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/ArchiveConductor.java#L194-L230","documentation":"ArchiveConductor obtains the Authenticator by calling ctx.authenticatorSupplier().get() at startup. The archive requires a real authenticator even if no authentication is needed (use a no-op one), so a null result is rejected with ArchiveException. This guards against suppliers that return null by default.","triggerScenarios":"Launching Archive with an authenticatorSupplier whose get() returns null (e.g. a lambda that fails to instantiate, or a default supplier returning null).","commonSituations":"Custom AuthenticationSupplier implementations with broken lazy initialization;DI frameworks injecting null when no bean is defined.","solutions":["Fix the authenticatorSupplier to return a non-null Authenticator instance.","If authentication is not required, supply a permissive no-op Authenticator (e.g. a singleton that always authorises).","Use Archive.Configuration.authenticatorSupplier() default, which returns a valid no-op authenticator."],"exampleFix":"// before\nctx.authenticatorSupplier(() -> null);\n// after\nctx.authenticatorSupplier(() -> new Authenticator()\n{\n    public void onConnectRequest(...) { session.response(...); /* accept */ }\n    public void onChallengeResponse(...) { }\n    public void onConnectedSession(Session session) { session.accept(); }\n    public void onChallengedSession(Session session) { }\n});","handlingStrategy":"validation","validationCode":"Authenticator a = ctx.authenticatorSupplier().get();\nif (a == null)\n{\n    throw new IllegalStateException(\"authenticatorSupplier must return a non-null Authenticator\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never write suppliers that return null; return a no-op/permissive Authenticator instead","Test archive startup with the real supplier wiring before deployment"],"tags":["aeron","archive","authentication","null"],"backgroundTag":"null-argument","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}