spring-projects/spring-security · error · UnsupportedOperationException
%s does not store credentials
Error message
%s does not store credentials
What it means
The default Authentication.Builder#credentials(Object) method throws UnsupportedOperationException('... does not store credentials') because that builder's Authentication implementation does not support holding credentials. Builders of credential-less Authentication types (e.g. pre-authenticated or token types that intentionally drop secrets) inherit this default and fail fast if credentials are set. [SOURCE context: core/src/main/java/org/springframework/security/core/Authentication.java:196]
Source
Thrown at core/src/main/java/org/springframework/security/core/Authentication.java:196
* @return the {@link Builder} for additional configuration
* @see Authentication#getAuthorities
*/
B authorities(Consumer<Collection<GrantedAuthority>> authorities);
/**
* Use this credential.
* <p>
* Note that since some credentials are insecure to store, this method is
* implemented as unsupported by default. Only implement or use this method if you
* support secure storage of the credential or if your implementation also
* implements {@link CredentialsContainer} and the credentials are thereby erased.
* </p>
* @param credentials the credentials to use
* @return the {@link Builder} for additional configuration
* @see Authentication#getCredentials
*/
default B credentials(@Nullable Object credentials) {
throw new UnsupportedOperationException(
String.format("%s does not store credentials", this.getClass().getSimpleName()));
}
/**
* Use this details object.
* <p>
* Implementations may choose to use these {@code details} in combination with any
* principal from the pre-existing {@link Authentication} instance.
* </p>
* @param details the details to use
* @return the {@link Builder} for additional configuration
* @see Authentication#getDetails
*/
B details(@Nullable Object details);
/**
* Use this principal.
* <p>View on GitHub (pinned to 96852e8860)
Solutions
- Stop calling .credentials() on builders for Authentication types that do not store credentials; put the secret only into the initial token constructor
- Check the concrete Authentication/Builder class documentation (Javadoc on Authentication.Builder#credentials) to confirm credential support
- If credential storage is needed, use or implement a builder that overrides credentials() with real storage
Example fix
// before
MyToken t = SomeNonCredentialAuthentication.builder()
.principal(principal)
.credentials(secret) // throws
.build();
// after
MyToken t = new UsernamePasswordAuthenticationToken(principal, secret); // credential-capable type Defensive patterns
Strategy: type-guard
Validate before calling
if (!authenticationTypeStoresCredentials(builderClass)) { throw new IllegalArgumentException("this Authentication type does not support credentials()"); } Type guard
boolean supportsCredentials(Authentication.Builder b) { try { return !(b.getClass().getMethod("credentials", Object.class).getDeclaringClass().equals(Authentication.Builder.class)); } catch (NoSuchMethodException e) { return false; } } Try / catch
try { builder.credentials(secret); } catch (UnsupportedOperationException e) { throw new IllegalArgumentException("this authentication type does not store credentials"); } Prevention
- Only call .credentials() on builders documented to store credentials
- Pass secrets through the token constructor instead of a generic builder chain
- Avoid generic helper methods that blindly call .credentials() on any Authentication.Builder
When it happens
Trigger: Calling .credentials(...) on a builder whose resulting Authentication class does not implement a credentials-capable builder (only overrides getCredentials semantics); copy-pasting builder code between Authentication types where one stores credentials and the other does not.
Common situations: Refactoring authentication code and reusing a builder chain across token types; framework upgrades introducing a default builder method that some Authentication implementations never supported; writing generic code that uniformly calls .credentials() on any Authentication.Builder.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot apply {configurer} to already built object
- This object has already been built
- This object has not been built
- encode is not supported
- Unsupported key selector type + jwsKeySelector.getClass()
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/d6921d900fb4b434.
Report an issue: GitHub.