{"record":{"id":"95a1a7de052f2240","repo":"quarkusio/quarkus","slug":"could-not-obtain-credential","errorCode":null,"errorMessage":"Could not obtain credential","messagePattern":"Could not obtain credential","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/QuarkusDirContextFactory.java","lineNumber":59,"sourceCode":"\n    @Override\n    public DirContext obtainDirContext(ReferralMode mode) throws NamingException {\n        char[] charPassword = null;\n        if (securityCredential != null) { // password from String\n            charPassword = securityCredential.toCharArray();\n        }\n        return createDirContext(securityPrincipal, charPassword, mode);\n    }\n\n    @Override\n    public DirContext obtainDirContext(CallbackHandler handler, ReferralMode mode) throws NamingException {\n        NameCallback nameCallback = new NameCallback(\"Principal Name\");\n        PasswordCallback passwordCallback = new PasswordCallback(\"Password\", false);\n\n        try {\n            handler.handle(new Callback[] { nameCallback, passwordCallback });\n        } catch (Exception e) {\n            throw new RuntimeException(\"Could not obtain credential\", e);\n            //            throw log.couldNotObtainCredentialWithCause(e);\n        }\n\n        String securityPrincipal = nameCallback.getName();\n\n        if (securityPrincipal == null) {\n            throw new RuntimeException(\"Could not obtain principal\");\n            //            throw log.couldNotObtainPrincipal();\n        }\n\n        char[] securityCredential = passwordCallback.getPassword();\n\n        if (securityCredential == null) {\n            throw new RuntimeException(\"Could not obtain credential\");\n            //            throw log.couldNotObtainCredential();\n        }\n\n        return createDirContext(securityPrincipal, securityCredential, mode);","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/QuarkusDirContextFactory.java#L41-L77","documentation":"QuarkusDirContextFactory.obtainDirContext uses an Elytron CallbackHandler to collect the LDAP bind principal and password via NameCallback/PasswordCallback. If handler.handle(...) throws (or any exception occurs while obtaining the credentials), the method wraps it in a RuntimeException('Could not obtain credential'). This means the configured credential supplier could not provide the bind credentials, before any LDAP connection is even attempted.","triggerScenarios":"The CallbackHandler (typically a supplied credential supplier / properties-based handler) throws while handling the callbacks — e.g. the backing supplier throws SecurityException or the configured identity/credential supplier is missing or fails.","commonSituations":"quarkus.elytron.security.ldap directory context factory configured with a custom credential supplier that fails; missing configuration so the handler cannot resolve the bind principal/password; wrapped exception's cause shows the real error (missing config key, security exception).","solutions":["Inspect the cause of the RuntimeException (it wraps the original exception) to find the real failure.","Verify the LDAP config (quarkus.elytron.security.ldap.*): the identity/credential supplying properties are set and correct.","If a custom CallbackHandler/credential supplier is registered, ensure it handles NameCallback and PasswordCallback without throwing.","Test the bind credentials directly against the LDAP server (e.g. ldapwhoami) to rule out credential problems."],"exampleFix":"// before: handler that returns nothing and throws on NameCallback\ncallbackHandler = cfg -> { throw new IllegalStateException(\"not configured\"); };\n// after: provide both callbacks\nbindingConfig.setCallbackHandler(callbacks -> {\n    for (Callback cb : callbacks) {\n        if (cb instanceof NameCallback) ((NameCallback) cb).setName(dn);\n        if (cb instanceof PasswordCallback) ((PasswordCallback) cb).setPassword(pwd);\n    }\n});","handlingStrategy":"try-catch","validationCode":"// verify LDAP bind configuration before touching DirContext\nif (config.principal() == null || config.principal().isBlank()) {\n    throw new IllegalStateException(\"LDAP bind principal not configured\");\n}\nif (config.password() == null) {\n    throw new IllegalStateException(\"LDAP bind password not configured\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    DirContext ctx = dirContextFactory.obtainDirContext();\n} catch (RuntimeException e) {\n    if (\"Could not obtain credential\".equals(e.getMessage())) {\n        throw new DeploymentException(\"LDAP credential supplier failed\", e.getCause());\n    }\n    throw e;\n}","preventionTips":["Inspect the wrapped cause — it names the real failing component.","Validate LDAP config properties at application startup.","Test bind credentials against the LDAP server out-of-band (ldapwhoami).","Keep custom CallbackHandler implementations simple and null-safe."],"tags":["ldap","elytron","security","configuration"],"backgroundTag":"ldap-bind-credential-error","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}