quarkusio/quarkus · warning · IllegalArgumentException

null s-maxage

Error message

null s-maxage

What it means

IllegalArgumentException from CacheControlDelegate.fromString: while parsing a Cache-Control header directive that takes a delta-seconds value (s-maxage or max-age), no numeric value followed the '=' — e.g. 's-maxage='. The named directive (in the message) lacks its required numeric argument.

Source

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

            if ("no-cache".equals(lowercase)) {
                result.setNoCache(true);
                if (val != null && !"".equals(val)) {
                    result.getNoCacheFields().add(val);
                }
            } else if ("private".equals(lowercase)) {
                result.setPrivate(true);
                if (val != null && !"".equals(val)) {
                    result.getPrivateFields().add(val);
                }
            } else if ("no-store".equals(lowercase)) {
                result.setNoStore(true);
            } else if ("max-age".equals(lowercase)) {
                if (val == null)
                    throw new IllegalArgumentException("null max age");
                result.setMaxAge(Integer.valueOf(val));
            } else if ("s-maxage".equals(lowercase)) {
                if (val == null)
                    throw new IllegalArgumentException("null s-maxage");
                result.setSMaxAge(Integer.valueOf(val));
            } else if ("no-transform".equals(lowercase)) {
                result.setNoTransform(true);
            } else if ("must-revalidate".equals(lowercase)) {
                result.setMustRevalidate(true);
            } else if ("proxy-revalidate".equals(lowercase)) {
                result.setProxyRevalidate(true);
            } else if ("public".equals(lowercase)) {
                result.setPublic(true);
            } else {
                if (val == null)
                    val = "";
                result.getCacheExtension().put(name, val);
            }
        }
        return result;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Fix the directive to 's-maxage=<seconds>'
  2. Validate header values before parsing
  3. Correct the CDN/proxy configuration emitting the malformed directive
  4. Catch IllegalArgumentException and fall back to ignoring shared-cache directives

Example fix

// before
Cache-Control: public, s-maxage
// after
Cache-Control: public, s-maxage=600
Defensive patterns

Strategy: validation

Validate before calling

if (directive.startsWith("s-maxage") && !directive.matches("s-maxage=\\d+")) { throw new IllegalArgumentException("s-maxage requires a numeric value: " + directive); }

Try / catch

try {
    CacheControl cc = CacheControlDelegate.INSTANCE.fromString(headerValue);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("s-maxage")) { /* ignore shared-cache directive or fail fast */ }
}

Prevention

When it happens

Trigger: A Cache-Control header string containing 's-maxage' with no value, e.g. 'Cache-Control: public, s-maxage', parsed via CacheControlDelegate.fromString.

Common situations: CDN (Fastly/CloudFront/Varnish) configurations emitting a valueless s-maxage; hand-rolled header generation missing the value; typos like 's-maxage 600' (space instead of =).

Related errors


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