ben-manes/caffeine · error · IllegalArgumentException

key %s value was set to %s, must be a long

Error message

key %s value was set to %s, must be a long

What it means

CaffeineSpec.parseLong is the 64-bit counterpart of parseInt and throws IllegalArgumentException("key %s value was set to %s, must be a long") when a long-valued option (e.g. maximumSize with large values, durations in simple format) cannot be parsed. The key and offending value are included in the message for quick diagnosis.

Source

Thrown at caffeine/src/main/java/com/github/benmanes/caffeine/cache/CaffeineSpec.java:291

  static int parseInt(String key, @Nullable String value) {
    requireArgument((value != null) && !value.isEmpty(), "value of key %s was omitted", key);
    requireNonNull(value);
    try {
      return Integer.parseInt(normalizeNumericLiteral(value));
    } catch (NumberFormatException e) {
      throw new IllegalArgumentException(String.format(US,
          "key %s value was set to %s, must be an integer", key, value), e);
    }
  }

  /** Returns a parsed long value. */
  static long parseLong(String key, @Nullable String value) {
    requireArgument((value != null) && !value.isEmpty(), "value of key %s was omitted", key);
    requireNonNull(value);
    try {
      return Long.parseLong(normalizeNumericLiteral(value));
    } catch (NumberFormatException e) {
      throw new IllegalArgumentException(String.format(US,
          "key %s value was set to %s, must be a long", key, value), e);
    }
  }

  /** Returns the value after adjusting for underscores in a numeric literal. */
  static String normalizeNumericLiteral(String value) {
    boolean invalid = value.startsWith("+_") || value.startsWith("-_")
        || value.startsWith("_") || value.endsWith("_");
    return invalid ? value : value.replace("_", "");
  }

  /** Returns a parsed duration value. */
  static Duration parseDuration(String key, @Nullable String value) {
    requireArgument((value != null) && !value.isEmpty(), "value of key %s omitted", key);
    requireNonNull(value);

    boolean isIsoFormat = value.contains("p") || value.contains("P");
    Duration duration = isIsoFormat

View on GitHub (pinned to 9da6581ee3)

Solutions

  1. Supply a plain (optionally underscore-separated) decimal integer within the long range
  2. For very large capacities, prefer maximumWeight with an appropriate weighing function instead of raw counts
  3. Validate externally sourced numbers with Long.parseLong before embedding them into a spec string

Example fix

# before
Caffeine.from("maximumSize=1e9") // IllegalArgumentException: must be a long

# after
Caffeine.from("maximumSize=1000000000")
Defensive patterns

Strategy: validation

Validate before calling

// Validate long options before building the spec:
String normalized = rawValue.strip().replace("_", "").replace(",", "");
try {
  long v = Long.parseLong(normalized);
  if (v < 0) throw new ConfigException("negative capacity: " + rawValue);
} catch (NumberFormatException e) {
  throw new ConfigException("Expected long, got: " + rawValue, e);
}

Try / catch

try {
  return Caffeine.from(spec);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().contains("must be a long")) {
    throw new ConfigException("Invalid long value in cache spec", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Caffeine.from("maximumSize=9_223_372_036_854_775_808") (Long.MAX_VALUE+1); a simple duration like "expireAfterWrite=30x" reaching parseLong with a non-numeric body; values with commas or scientific notation ("maximumSize=1e6").

Common situations: Overflowing maximumSize/maximumWeight beyond Long range; locale-formatted or scientific-notation numbers from config systems; malformed duration bodies that fail before the time-unit check.

Related errors


AI-assisted analysis of ben-manes/caffeine@9da6581ee3 (2026-08-14). Data as JSON: /api/errors/9a06f1271934d3b2. Report an issue: GitHub.