quarkusio/quarkus · error · RuntimeException

Missing password provider for password type: ${passwordType}

Error message

Missing password provider for password type: ${passwordType}

What it means

JpaSecurityIdentityUtil.buildIdentity() generates bytecode for the JPA identity provider. When the entity's password field is declared as PasswordType.CUSTOM, a PasswordProvider must be supplied via configuration; if passwordProviderValue is null, it throws RuntimeException because it cannot generate password-verification code without the provider class.

Source

Thrown at extensions/security-jpa-common/deployment/src/main/java/io/quarkus/security/jpa/common/deployment/JpaSecurityIdentityUtil.java:64

            PanacheEntityPredicateBuildItem panacheEntityPredicate, FieldDesc passwordProviderField,
            Expr thisRef, Expr requestParam, Expr userVar, BlockCreator bc) {
        // if(user == null) throw new AuthenticationFailedException();

        PasswordType passwordType = passwordTypeValue != null ? PasswordType.valueOf(passwordTypeValue.asEnum())
                : PasswordType.MCF;

        bc.if_(bc.isNull(userVar), trueBranch -> {
            Expr exceptionInstance = trueBranch
                    .new_(ConstructorDesc.of(AuthenticationFailedException.class));
            trueBranch.invokeStatic(passwordActionMethod(), Const.of(passwordType));
            trueBranch.throw_(exceptionInstance);
        });

        // :pass = user.pass | user.getPass()
        LocalVar pass = bc.localVar("pass", jpaSecurityDefinition.password.readValue(bc, userVar));

        if (passwordType == PasswordType.CUSTOM && passwordProviderValue == null) {
            throw new RuntimeException("Missing password provider for password type: " + passwordType);
        }

        Expr storedPassword;
        switch (passwordType) {
            case CUSTOM:
                String passwordProviderClassStr = passwordProviderValue.asString();
                String passwordProviderMethod = "getPassword";
                LocalVar passwordProviderInstanceField = bc.localVar("ppField",
                        bc.get(thisRef.field(passwordProviderField)));
                bc.if_(bc.isNull(passwordProviderInstanceField), trueBranch -> {
                    Expr passwordProviderInstance = trueBranch
                            .new_(ConstructorDesc.of(ClassDesc.of(passwordProviderClassStr)));
                    trueBranch.set(thisRef.field(passwordProviderField), passwordProviderInstance);
                });
                LocalVar objectToInvokeOn = bc.localVar("ppObj",
                        bc.get(thisRef.field(passwordProviderField)));

                // :getPasswordMethod(:pass);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Configure the password provider class for the entity, e.g. via the @Password attribute value or the corresponding quarkus.security-jpa config property.
  2. Use a built-in PasswordType (BCRYPT, etc.) instead of CUSTOM if a provider is not available.
  3. Implement a PasswordProvider for your hash algorithm and reference it.

Example fix

// before
@Password(PasswordType.CUSTOM)
private String password;

// after
@Password(value = PasswordType.CUSTOM, provider = com.app.LegacyPasswordProvider.class)
private String password;
Defensive patterns

Strategy: validation

Validate before calling

if (passwordType == PasswordType.CUSTOM && passwordProviderClass == null) {
    throw new IllegalStateException("CUSTOM requires a PasswordProvider");
}

Prevention

When it happens

Trigger: Annotating the password field/setter with @Password(PasswordType.CUSTOM) without registering a PasswordProvider implementation/pointing to one in configuration.

Common situations: Choosing CUSTOM for a legacy hash algorithm but forgetting to specify the provider class; renaming/removing the PasswordProvider class so the config value no longer resolves; copy-pasting an entity definition with CUSTOM type from an example that included a provider.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e42911e0d056da59. Report an issue: GitHub.