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

  1. Stop calling .credentials() on builders for Authentication types that do not store credentials; put the secret only into the initial token constructor
  2. Check the concrete Authentication/Builder class documentation (Javadoc on Authentication.Builder#credentials) to confirm credential support
  3. 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

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


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/d6921d900fb4b434. Report an issue: GitHub.