apache/pulsar · error · IOException

Invalid allowed offset for athenz role token verification sp

Error message

Invalid allowed offset for athenz role token verification specified

What it means

After reading domain names, initialize() optionally parses the allowed clock offset for Athenz role token verification from a system property. If the value is not a valid integer, Integer.parseInt throws NumberFormatException which is wrapped into this IOException. The offset is used to tolerate clock skew when validating token timestamps.

Source

Thrown at pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java:84

                getClass().getSimpleName(), getAuthMethodName());
        var config = context.getConfig();
        String domainNames;
        if (config.getProperty(DOMAIN_NAME_LIST) != null) {
            domainNames = (String) config.getProperty(DOMAIN_NAME_LIST);
        } else if (!StringUtils.isEmpty(System.getProperty(SYS_PROP_DOMAIN_NAME_LIST))) {
            domainNames = System.getProperty(SYS_PROP_DOMAIN_NAME_LIST);
        } else {
            throw new IOException("No athenz domain name specified");
        }

        domainNameList = Lists.newArrayList(domainNames.split(","));
        log.info().attr("domainNames", domainNameList).log("Supported domain names for Athenz");

        if (!StringUtils.isEmpty(System.getProperty(SYS_PROP_ALLOWED_OFFSET))) {
            try {
                allowedOffset = Integer.parseInt(System.getProperty(SYS_PROP_ALLOWED_OFFSET));
            } catch (NumberFormatException e) {
                throw new IOException("Invalid allowed offset for athenz role token verification specified", e);
            }

            if (allowedOffset < 0) {
                throw new IOException("Allowed offset for athenz role token verification must not be negative");
            }
        }

        log.info().attr("allowedOffsetSeconds", allowedOffset).log("Allowed offset for athenz role token verification");
    }

    @Override
    public String getAuthMethodName() {
        return "athenz";
    }

    @Override
    public void incrementFailureMetric(Enum<?> errorCode) {
        authenticationMetrics.recordFailure(errorCode);

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the system property to a plain integer number of seconds, e.g. -D<allowedOffsetSysProp>=30.
  2. Remove the system property entirely to use the default offset.
  3. Check for stray quotes, units, or whitespace in launcher scripts, docker env files, or k8s manifests.

Example fix

// before
PULSAR_GC_OPTS="-Dathenz.allowed.offset=30s"
// after
PULSAR_GC_OPTS="-Dathenz.allowed.offset=30"
Defensive patterns

Strategy: validation

Validate before calling

String off = System.getProperty(ATHENZ_SYS_PROP_ALLOWED_OFFSET);
if (off != null && !off.isEmpty()) {
    try { Integer.parseInt(off.trim()); }
    catch (NumberFormatException e) { throw new IllegalArgumentException("allowed offset must be plain integer seconds: " + off); }
}

Try / catch

try {
    provider.initialize(config);
} catch (IOException e) {
    if (e.getMessage().contains("Invalid allowed offset")) {
        log.error("Fix the offset system property to a plain integer of seconds");
    }
    throw e;
}

Prevention

When it happens

Trigger: System property SYS_PROP_ALLOWED_OFFSET is set (non-empty) but its value is non-numeric, e.g. '30s', 'thirty', or contains whitespace/units.

Common situations: Operator wrote '-Dathenz.allowed.offset=30 seconds' or '30s' instead of plain integer seconds; quoting issues in systemd/docker env passing stray characters.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/e49b558d9fc02aeb. Report an issue: GitHub.