quarkusio/quarkus · warning · BadRequestException
Unclosed quotes:
Error message
Unclosed quotes:
What it means
When a parameter value starts with a quote, parseParameters() scans for the closing quote, allowing escaped quotes (\". If no unescaped closing quote exists in the header, this BadRequestException is thrown.
Source
Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/request/AcceptHeaders.java:179
//LogMessages.LOGGER.debug(result.toString());
return result;
}
private static int parseParameters(Map<String, String> parameters, String header, int offset) {
while (true) {
int equalsIndex = header.indexOf('=', offset);
if (equalsIndex < 0)
throw new BadRequestException("Malformed parameters: " + header);
String name = header.substring(offset, equalsIndex).trim();
offset = equalsIndex + 1;
if (header.charAt(offset) == '"') {
int end = offset;
++offset;
do {
end = header.indexOf('"', ++end);
if (end < 0)
throw new BadRequestException("Unclosed quotes:" + header);
} while (header.charAt(end - 1) == '\\');
String value = header.substring(offset, end);
parameters.put(name, value);
offset = end + 1;
int parameterEndIndex = header.indexOf(';', offset);
int itemEndIndex = header.indexOf(',', offset);
if (parameterEndIndex == itemEndIndex) {
assert itemEndIndex == -1;
if (header.substring(offset).trim().length() != 0)
throw new BadRequestException("Extra characters after quoted string:" + header);
return -1;
} else if (parameterEndIndex < 0 || (itemEndIndex >= 0 && itemEndIndex < parameterEndIndex)) {
if (header.substring(offset, itemEndIndex).trim().length() != 0)
throw new BadRequestException("Extra characters after quoted string:" + header);
return itemEndIndex + 1;
} else {
if (header.substring(offset, parameterEndIndex).trim().length() != 0)View on GitHub (pinned to e1c734241f)
Solutions
- Close the quoted parameter value with a matching '"'
- Escape embedded quotes as \" inside quoted values
- Avoid quotes for simple parameter values (e.g. charset=utf-8 needs none)
Example fix
// before Accept: application/json;x="foo // after Accept: application/json;x="foo\"bar" or Accept: application/json;x=foo
Defensive patterns
Strategy: validation
Validate before calling
boolean quotesAreBalanced(String header) {
if (header == null) return false;
long count = header.chars().filter(c -> c == '"').count();
return count % 2 == 0;
} Type guard
boolean hasBalancedQuotes(String header) {
return header == null || header.replaceAll("\\\\\"", "").chars()
.filter(c -> c == '"').count() % 2 == 0;
} Try / catch
try {
types = AcceptHeaders.getMediaTypeQualityValues(accept);
} catch (BadRequestException e) {
types = Collections.emptyMap();
} Prevention
- Escape embedded quotes as \" inside quoted parameter values
- Prefer unquoted simple parameter values
- Escape quotes before serializing user input into header parameters
When it happens
Trigger: Accept header with an unbalanced quoted parameter, e.g. 'application/json;x="foo' — the opening quote is never closed.
Common situations: Programmatic header construction with unescaped quotes; values containing quotes intended as literals; copy-paste of header examples missing the closing quote.
Related errors
- Extra characters after quoted string:
- param was null
- Param was null
- Does not support fromString
- Unsupported parameter:
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4eb78570a9fbd862.
Report an issue: GitHub.