spring-projects/spring-ai · error · IllegalArgumentException

NoSuchAlgorithmException (wrapped IllegalArgumentException)

Error message

NoSuchAlgorithmException (wrapped IllegalArgumentException)

What it means

JdkSha256HexIdGenerator resolves a MessageDigest via MessageDigest.getInstance(algorithm) in its constructor; unsupported algorithm names throw NoSuchAlgorithmException, wrapped in IllegalArgumentException. The default constructor uses SHA-256, so this only occurs when supplying a custom algorithm.

Source

Thrown at spring-ai-commons/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java:51

 * @author Christian Tzolov
 */
public class JdkSha256HexIdGenerator implements IdGenerator {

	private static final String SHA_256 = "SHA-256";

	private final String byteHexFormat = "%02x";

	private final Charset charset;

	private final MessageDigest messageDigest;

	public JdkSha256HexIdGenerator(final String algorithm, final Charset charset) {
		this.charset = charset;
		try {
			this.messageDigest = MessageDigest.getInstance(algorithm);
		}
		catch (NoSuchAlgorithmException e) {
			throw new IllegalArgumentException(e);
		}
	}

	public JdkSha256HexIdGenerator() {
		this(SHA_256, StandardCharsets.UTF_8);
	}

	@Override
	public String generateId(Object... contents) {
		return this.hash(this.serializeToBytes(contents));
	}

	// https://github.com/spring-projects/spring-ai/issues/113#issue-2000373318
	private String hash(byte[] contentWithMetadata) {
		byte[] hashBytes = getMessageDigest().digest(contentWithMetadata);
		StringBuilder sb = new StringBuilder();
		for (byte b : hashBytes) {
			sb.append(String.format(this.byteHexFormat, b));

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Use the no-arg constructor which defaults to SHA-256
  2. Use a standard JDK algorithm name: 'SHA-256', 'SHA-512', 'MD5'
  3. Check available algorithms: Security.getAlgorithms("MessageDigest")
  4. Catch IllegalArgumentException at construction and fall back to SHA-256

Example fix

// before
IdGenerator gen = new JdkSha256HexIdGenerator(config.getHashAlgo(), UTF_8);
// after
String algo = Security.getAlgorithms("MessageDigest").contains(config.getHashAlgo()) ? config.getHashAlgo() : "SHA-256";
IdGenerator gen = new JdkSha256HexIdGenerator(algo, UTF_8);
Defensive patterns

Strategy: validation

Validate before calling

if (!Security.getAlgorithms("MessageDigest").contains(algorithm)) {
    throw new IllegalArgumentException("Unsupported digest algorithm: " + algorithm);
}
new JdkSha256HexIdGenerator(algorithm, charset);

Try / catch

try {
    gen = new JdkSha256HexIdGenerator(algo, charset);
} catch (IllegalArgumentException e) {
    gen = new JdkSha256HexIdGenerator(); // fallback to SHA-256
}

Prevention

When it happens

Trigger: new JdkSha256HexIdGenerator("SHA3-999", charset) or any algorithm string not provided by the installed JCE providers (typo like 'sha256' is usually fine — JDK is case-insensitive — but e.g. 'MD6' or a FIPS-restricted JDK lacking the algorithm fails).

Common situations: Configuring a custom hash algorithm via properties on a hardened/FIPS JVM where the requested provider isn't installed, or typos in algorithm names.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/26959db37a74d63e. Report an issue: GitHub.