spring-projects/spring-security · error · IllegalArgumentException

Couldn't find closing brace for SHA prefix

Error message

Couldn't find closing brace for SHA prefix

What it means

extractPrefix parses the {prefix} header of an encoded password. If the string starts with '{' but contains no '}', lastIndexOf returns -1 and this IllegalArgumentException is thrown. The stored hash is malformed — an opening brace without its closing brace — so the prefix cannot be determined.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java:177

			return extractSalt(encodedPassword);
		}
		if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) {
			throw new IllegalArgumentException("Unsupported password prefix '" + prefix + "'");
		}
		// Standard SHA
		return null;
	}

	/**
	 * Returns the hash prefix or null if there isn't one.
	 */
	private @Nullable String extractPrefix(String encPass) {
		if (!encPass.startsWith("{")) {
			return null;
		}
		int secondBrace = encPass.lastIndexOf('}');
		if (secondBrace < 0) {
			throw new IllegalArgumentException("Couldn't find closing brace for SHA prefix");
		}
		return encPass.substring(0, secondBrace + 1);
	}

	public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) {
		this.forceLowerCasePrefix = forceLowerCasePrefix;
	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Inspect the stored value and restore the full hash including the closing '}' (e.g. "{SSHA}base64hashsalt").
  2. Re-encode the password with LdapShaPasswordEncoder and replace the corrupted entry.
  3. Widen the storage column or fix the import/export code that truncates hashes.

Example fix

// before
String stored = "{SSHAbXcgLi4u"; // missing '}'
// after
String stored = "{SSHA}bXcgLi4uZXhhbXBsZQ==";
Defensive patterns

Strategy: validation

Validate before calling

boolean wellFormed = stored.startsWith("{") && stored.indexOf('}') > 0;
if (!wellFormed) throw new IllegalArgumentException("stored hash missing '{...}' prefix");

Try / catch

try {
    ok = ldapEncoder.matches(raw, stored);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("closing brace")) {
        // mark record corrupted and force password reset
    }
}

Prevention

When it happens

Trigger: Calling encode/matches with an encodedPassword like "{SSHAabc123..." where the closing '}' after the algorithm name was lost due to truncation, manual editing, or a broken import.

Common situations: Database column too short truncating the stored hash right after '{'; copy/paste dropping the brace; hand-written seed fixtures with malformed prefixes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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