quarkusio/quarkus · error · IllegalArgumentException

Too many links

Error message

Too many links

What it means

LinkDelegate.parse builds a Link object from a Link header string. The grammar allows exactly one <uri> target; if a second '<' character is encountered after an href has already been parsed, the string contains multiple links, which this parser does not support, so it throws IllegalArgumentException("Too many links").

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/headers/LinkDelegate.java:42

        Parser(final String value) {
            this.value = value;
            builder = new LinkBuilderImpl();
        }

        public Link getLink() {
            return builder.build();
        }

        public void parse() {
            String href = null;
            MultivaluedMap<String, String> attributes = new QuarkusMultivaluedHashMap<String, String>();
            while (curr < value.length()) {

                char c = value.charAt(curr);
                if (c == '<') {
                    if (href != null)
                        throw new IllegalArgumentException("Too many links");
                    href = parseLink();
                } else if (c == ';' || c == ' ') {
                    curr++;
                    continue;
                } else {
                    parseAttribute(attributes);
                }
            }
            populateLink(href, attributes);

        }

        protected void populateLink(String href, MultivaluedMap<String, String> attributes) {
            builder.uri(href);
            for (String name : attributes.keySet()) {
                List<String> values = attributes.get(name);
                if (name.equals("rel")) {
                    for (String val : values)

View on GitHub (pinned to e1c734241f)

Solutions

  1. Split the header on the link separator and parse each link individually (or use a MultivaluedMap so each Link header is a separate value)
  2. Parse only the first link via a regex capturing one <...>; rel=... group
  3. Fix the server/proxy to emit separate Link headers instead of a merged value
  4. Wrap parse in try-catch if multiple links are expected and handle them by splitting on ',\s*</' boundaries

Example fix

// before
Link link = LinkDelegate.INSTANCE.fromString("</next>; rel=\"next\", </prev>; rel=\"prev\""); // throws
// after
for (String part : headerValue.split(",(?=\s*<)")) {
    Link link = LinkDelegate.INSTANCE.fromString(part.trim());
    // handle each link
}
Defensive patterns

Strategy: try-catch

Validate before calling

long targets = headerValue.chars().filter(c -> c == '<').count();
if (targets > 1) { /* split on commas and parse each link separately */ }

Try / catch

try {
    Link link = LinkDelegate.INSTANCE.fromString(value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Too many links")) {
        // split value on ",(?=\s*<)" and parse each part
    }
}

Prevention

When it happens

Trigger: Passing a multi-value Link header string like '</page/2>; rel="next", </page/1>; rel="prev"' to LinkDelegate.parse/fromString, or a malformed value containing two <...> targets.

Common situations: REST APIs emitting comma-separated Link headers (pagination per RFC 8288) being parsed with a single-Link parser; concatenated header values from proxies that merge Link headers.

Related errors


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