zaproxy/zaproxy · error · URIException
Invalid query
Error message
Invalid query
What it means
In escaped mode (true passed to the constructor / parseUriReference) the query string after '?' is validated against the allowed query character set (uric). If it contains characters that are neither allowed nor properly percent-escaped, URIException("Invalid query") is thrown.
Source
Thrown at zap/src/main/java/org/apache/commons/httpclient/URI.java:2159
String charset = getProtocolCharset();
/*
* Parse the query component.
* <p><blockquote><pre>
* query = $7 = <undefined>
* @@@@@@@@@
* ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
* </pre></blockquote><p>
*/
if (0 <= at && at + 1 < length && tmp.charAt(at) == '?') {
int next = tmp.indexOf('#', at + 1);
if (next == -1) {
next = tmp.length();
}
if (escaped) {
_query = tmp.substring(at + 1, next).toCharArray();
if (!validate(_query, uric)) {
throw new URIException("Invalid query");
}
} else {
_query = encode(tmp.substring(at + 1, next), allowed_query, charset);
}
at = next;
}
/*
* Parse the fragment component.
* <p><blockquote><pre>
* fragment = $9 = Related
* @@@@@@@@
* ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
* </pre></blockquote><p>
*/
if (0 <= at && at + 1 <= length && tmp.charAt(at) == '#') {
if (at + 1 == length) { // empty fragment
_fragment = "".toCharArray();View on GitHub (pinned to 9d1970a436)
Solutions
- Percent-encode the query parameters (URLEncoder.encode / URIUtil.encode) before constructing the URI, or use the non-escaped constructor so the library encodes them.
- Replace raw spaces with %20 and encode non-ASCII characters in the query.
- Verify you picked the right constructor variant (escaped vs unescaped) for your input.
Example fix
// before
URI uri = new URI("http://example.com/search?q=" + term, true); // term = "hello world" -> Invalid query
// after
String encoded = java.net.URLEncoder.encode(term, "UTF-8");
URI uri = new URI("http://example.com/search?q=" + encoded, true);
// or let the library encode:
URI uri = new URI("http://example.com/search?q=" + term, false); Defensive patterns
Strategy: validation
Validate before calling
String encodeQuery(String raw) throws java.io.UnsupportedEncodingException {
return java.net.URLEncoder.encode(raw, "UTF-8");
}
// encode every name and value BEFORE building the query string Type guard
boolean isEscapedQuery(String q) {
return q != null && q.matches("[A-Za-z0-9-._~%!$&'()*+,;=:@/?#]*");
} Try / catch
try {
URI uri = new URI(url, true);
} catch (URIException e) {
if ("Invalid query".equals(e.getMessage())) {
// rebuild with URLEncoder.encode on each parameter and retry once
} else { throw e; }
} Prevention
- Always encode query parameter names and values with URLEncoder.encode.
- Use the unescaped URI constructor when your input is raw text.
- Never concatenate raw user input into a query string.
When it happens
Trigger: new URI("http://host/path?q=a b") or any query containing raw spaces, '<', '>', '"', '{', '}', '|', '\\', '^', '`' or non-ASCII characters while the escaped=true constructor is used, so the library validates instead of encoding.
Common situations: Building URLs by string concatenation with unencoded user input or search terms; non-ASCII (e.g. Chinese/Cyrillic) query parameters pasted in; query strings copied from logs that were partially decoded; using the escaped constructor with a not-yet-escaped URL.
Related errors
AI-assisted analysis of zaproxy/zaproxy@9d1970a436 (2026-09-05).
Data as JSON: /api/errors/6c2a6af45812003c.
Report an issue: GitHub.