apache/pulsar · error · IllegalArgumentException

Per instance ram requested, %s, for function should be posit

Error message

Per instance ram requested, %s, for function should be positive and a multiple of the granularity, %s

What it means

In the same admission check, KubernetesRuntimeFactory validates that the function's per-instance RAM is positive and an exact multiple of the configured RAM granularity (grnRam). If getResources().getRam() is 0 or not divisible by grnRam, doAdmissionChecks rejects the function with this IllegalArgumentException.

Source

Thrown at pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java:521

                // convert cpus to milli-cores to avoid loss of precision
                long grnCpuMillis = Math.round(baseMillis * grnCpu);
                if (grnCpuMillis > 0) {
                    long cpuMillis = Math.round(baseMillis * functionDetails.getResources().getCpu());
                    if (cpuMillis == 0 || cpuMillis % grnCpuMillis != 0) {
                        throw new IllegalArgumentException(
                                String.format("Per instance cpu requested, %s, for function should be positive and a "
                                                + "multiple of the granularity, %s",
                                        functionDetails.getResources().getCpu(), grnCpu));
                    }
                    if (functionInstanceResourceChangeInLockStep) {
                        multiples = cpuMillis / grnCpuMillis;
                    }
                }
            }
            if (grnRam != null && grnRam > 0) {
                if (functionDetails.getResources().getRam() == 0
                        || functionDetails.getResources().getRam() % grnRam != 0) {
                    throw new IllegalArgumentException(
                            String.format("Per instance ram requested, %s, "
                                            + "for function should be positive and a multiple of the granularity, %s",
                                    functionDetails.getResources().getRam(), grnRam));
                }
                if (functionInstanceResourceChangeInLockStep && multiples > 0) {
                    long ramMultiples = functionDetails.getResources().getRam() / grnRam;
                    if (multiples != ramMultiples) {
                        throw new IllegalArgumentException(
                                String.format("Per instance cpu requested, %s, ram requested, %s,"
                                                + " for function should be positive and the same multiple of the "
                                                + "granularity, cpu, %s, ram, %s",
                                        functionDetails.getResources().getCpu(),
                                        functionDetails.getResources().getRam(), grnCpu, grnRam));
                    }
                }
            }
        }
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Set resources.ram to a positive value that is an exact whole multiple of the configured RAM granularity in bytes.
  2. Round the requested RAM up to the next granularity step (e.g. granularity 1GB -> use 2147483648 for 2GB).
  3. Unset functionInstanceResourceGranularity in the worker config if per-cluster granularity enforcement is not wanted.
  4. If functionInstanceResourceChangeInLockStep is on, make sure the ram multiple matches the cpu multiple.

Example fix

// before (granularity = 1073741824 bytes)
resources:
  ram: 1500MB
// after
resources:
  ram: 2147483648  # 2GB, exact multiple
Defensive patterns

Strategy: validation

Validate before calling

long grnRam = configuredRamGranularityBytes; // from worker config
long ram = functionDetails.getResources().getRam();
if (ram <= 0 || ram % grnRam != 0) {
    throw new IllegalArgumentException("ram must be positive and a multiple of " + grnRam + " bytes");
}

Type guard

boolean isValidRam(Long ramBytes, long granularityBytes) {
    return ramBytes != null && ramBytes > 0 && granularityBytes > 0 && ramBytes % granularityBytes == 0;
}

Prevention

When it happens

Trigger: Submitting a function to the Kubernetes runtime when functionInstanceResourceGranularity defines a RAM granularity and FunctionDetails.getResources().getRam() is 0, negative, or not a whole multiple of grnRam (bytes).

Common situations: RAM left unset (0) while granularity is configured; RAM specified in MB/GB by hand and not landing on the granularity boundary (e.g. ram=1500MB with granularity 1GB = 1073741824 bytes); copying function configs between clusters with different granularity settings.

Related errors


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