spring-projects/spring-security · error · IllegalArgumentException
targetUri cannot contain query or fragment parts
Error message
targetUri cannot contain query or fragment parts
What it means
DPoPProofContext.validate rejects target URIs that contain a query string or fragment. Per RFC 9449, the DPoP proof htu claim must be the target URI without query or fragment components, so a URI with either is considered invalid input. This is thrown as an IllegalArgumentException after the URI passed URL parsing.
Source
Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofContext.java:178
return new DPoPProofContext(this.dPoPProof, this.method, this.targetUri, this.accessToken);
}
private void validate() {
if (!"GET".equals(this.method) && !"HEAD".equals(this.method) && !"POST".equals(this.method)
&& !"PUT".equals(this.method) && !"PATCH".equals(this.method) && !"DELETE".equals(this.method)
&& !"OPTIONS".equals(this.method) && !"TRACE".equals(this.method)) {
throw new IllegalArgumentException("method is invalid");
}
URI uri;
try {
uri = new URI(this.targetUri);
uri.toURL();
}
catch (Exception ex) {
throw new IllegalArgumentException("targetUri must be a valid URL", ex);
}
if (uri.getQuery() != null || uri.getFragment() != null) {
throw new IllegalArgumentException("targetUri cannot contain query or fragment parts");
}
}
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Strip the query and fragment before building the proof: use uriComponentsBuilder.replaceQuery(null).fragment(null).build().toUriString().
- Pass only the endpoint base URL for the token/resource request.
- If you need the request URL, reconstruct htu from scheme, host, port, and path only.
- Validate with uri.getQuery() == null && uri.getFragment() == null before calling the proof builder.
Example fix
// before
new DPoPProofContext("POST", "https://server/oauth2/token?grant_type=x", ...); // throws
// after
new DPoPProofContext("POST", "https://server/oauth2/token", ...); Defensive patterns
Strategy: validation
Validate before calling
URI uri = URI.create(targetUri);
if (uri.getQuery() != null || uri.getFragment() != null) {
throw new IllegalArgumentException("targetUri must not contain query or fragment");
} Type guard
boolean isBareEndpointUrl(String s) {
URI u = URI.create(s);
return u.getQuery() == null && u.getFragment() == null;
} Prevention
- Strip query/fragment before passing URLs to DPoP proof builders.
- Remember OAuth parameters belong in the POST body, not the token endpoint URL.
- Derive htu from the request's scheme/host/port/path only.
When it happens
Trigger: Constructing a DPoPProofContext with a targetUri like "https://server/oauth2/token?grant_type=client_credentials" or "https://server/oauth2/token#frag".
Common situations: Passing the full request URL (which includes query params) instead of the bare endpoint URL, or appending OAuth parameters to the token endpoint URL when they belong in the POST body.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- targetUri must be a valid URL
- method is invalid
- invalid_dpop_proof
- Unsupported alg parameter in JWS Header: ${algorithm.getName
- Missing jwk parameter in JWS Header.
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/9ecc30f59a1a30c8.
Report an issue: GitHub.