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

  1. Close the quoted parameter value with a matching '"'
  2. Escape embedded quotes as \" inside quoted values
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/4eb78570a9fbd862. Report an issue: GitHub.