quarkusio/quarkus · error · SpiffeConnectionException
SPIFFE ID must not contain userinfo: ${spiffeId}
Error message
SPIFFE ID must not contain userinfo: ${spiffeId} What it means
Per the SPIFFE standard, IDs must not contain a userinfo component (user@host syntax). SpiffeValidator.validateSpiffeId throws SpiffeConnectionException when URI.getUserInfo() returns non-null, since spiffe://user@example.org is not a valid SPIFFE ID.
Source
Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java:90
+ " bytes: " + spiffeId.length());
}
if (!spiffeId.startsWith(SPIFFE_URI_PREFIX)) {
throw new SpiffeConnectionException("SPIFFE ID must have 'spiffe://' scheme: " + spiffeId);
}
if (spiffeId.contains("%")) {
throw new SpiffeConnectionException("SPIFFE ID must not contain percent-encoded characters: " + spiffeId);
}
URI uri;
try {
uri = URI.create(spiffeId);
} catch (IllegalArgumentException e) {
throw new SpiffeConnectionException("SPIFFE ID is not a valid URI: " + spiffeId, e);
}
if (uri.getUserInfo() != null) {
throw new SpiffeConnectionException("SPIFFE ID must not contain userinfo: " + spiffeId);
}
if (uri.getPort() != -1) {
throw new SpiffeConnectionException("SPIFFE ID must not contain a port: " + spiffeId);
}
if (uri.getQuery() != null) {
throw new SpiffeConnectionException("SPIFFE ID must not contain a query: " + spiffeId);
}
if (uri.getFragment() != null) {
throw new SpiffeConnectionException("SPIFFE ID must not contain a fragment: " + spiffeId);
}
String trustDomain = uri.getHost();
if (trustDomain == null || trustDomain.isEmpty()) {
throw new SpiffeConnectionException("SPIFFE ID must have a non-empty trust domain: " + spiffeId);
}
if (trustDomain.length() > MAX_TRUST_DOMAIN_LENGTH) {
throw new SpiffeConnectionException("SPIFFE ID trust domain exceeds maximum length of "
+ MAX_TRUST_DOMAIN_LENGTH + " bytes: " + spiffeId);View on GitHub (pinned to e1c734241f)
Solutions
- Remove the userinfo portion so the ID starts directly with the trust domain (spiffe://example.org/...).
- Store credentials and SPIFFE IDs in separate configuration properties.
- Strip/validate user info where the ID string is assembled.
Example fix
// before String id = "spiffe://" + user + "@" + trustDomain + "/ns/default/sa/app"; // after String id = "spiffe://" + trustDomain + "/ns/default/sa/app";
Defensive patterns
Strategy: validation
Validate before calling
if (URI.create(spiffeId).getUserInfo() != null) {
throw new IllegalStateException("SPIFFE ID must not contain userinfo: " + spiffeId);
} Try / catch
try {
connection.establish();
} catch (SpiffeConnectionException e) {
if (e.getMessage().contains("userinfo")) {
log.error("SPIFFE ID contains user@host; separate credentials from identity config", e);
}
throw e;
} Prevention
- Never concatenate credentials or connection strings into SPIFFE IDs
- Keep auth config and identity config in distinct properties
- Validate the parsed URI parts before storing the ID
When it happens
Trigger: An ID like spiffe://admin@example.org/ns/default/sa/app — e.g. credentials accidentally prepended to the trust domain, or a URI assembled from a URL that includes user info.
Common situations: Copying a connection string (with username@host) into a SPIFFE ID field; templating that mixes authentication config with identity config; automated code that reuses a full URL as the ID.
Related errors
- SPIFFE ID exceeds maximum length of 2048 bytes: ${length}
- SPIFFE ID must have 'spiffe://' scheme: ${spiffeId}
- SPIFFE ID is not a valid URI: ${spiffeId}
- SPIFFE ID must not contain a port: ${spiffeId}
- SPIFFE ID must not contain a query:
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/1278664997e13c29.
Report an issue: GitHub.