apache/pulsar · error · IllegalArgumentException

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

Error message

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

What it means

KubernetesRuntimeFactory.validateResourcesGranularityAndProportion enforces that a function's requested CPU is positive and an exact multiple of the configured CPU granularity (functionInstanceResourceGranularity). The check converts both values to milli-cores to avoid floating-point loss of precision; if cpuMillis is 0 or cpuMillis % grnCpuMillis != 0, admission is rejected with this IllegalArgumentException during doAdmissionChecks.

Source

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

                                "Per instance RAM requested, %s, for function is greater than the maximum required, %s",
                                functionDetails.getResources().getRam(), maxRam));
            }
        }
    }

    void validateResourcesGranularityAndProportion(FunctionDetails functionDetails) {
        final long baseMillis = 1000;
        long multiples = 0L;
        if (functionInstanceResourceGranularities != null) {
            Double grnCpu = functionInstanceResourceGranularities.getCpu();
            Long grnRam = functionInstanceResourceGranularities.getRam();
            if (grnCpu != null) {
                // 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) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the function's resources.cpu to a positive value that is an exact multiple of the configured CPU granularity (e.g. granularity 0.5 -> use 0.5, 1.0, 1.5).
  2. If no granularity constraint is desired, unset/disable functionInstanceResourceGranularity in the worker config instead of fighting the modulo check.
  3. If resources were omitted, explicitly configure resources (cpu and ram) on the function manifest before submission.
  4. If functionInstanceResourceChangeInLockStep is enabled, also ensure the cpu multiple equals the ram multiple to avoid the follow-on error 1342.

Example fix

// before (granularity = 0.5)
resources:
  cpu: 0.35
// after
resources:
  cpu: 0.5
Defensive patterns

Strategy: validation

Validate before calling

long granularityMillis = Math.round(1000 * configuredCpuGranularity); // e.g. 0.5 -> 500
long cpuMillis = Math.round(1000 * functionDetails.getResources().getCpu());
if (cpuMillis <= 0 || cpuMillis % granularityMillis != 0) {
    throw new IllegalArgumentException("cpu must be positive and a multiple of " + configuredCpuGranularity);
}

Type guard

boolean isValidCpu(Double cpu, double granularity) {
    if (cpu == null || granularity <= 0) return false;
    long cpuMillis = Math.round(1000 * cpu);
    long grnMillis = Math.round(1000 * granularity);
    return cpuMillis > 0 && cpuMillis % grnMillis == 0;
}

Prevention

When it happens

Trigger: Submitting/updating a function (doAdmissionChecks) to a Kubernetes runtime where pulsar.functions.functionInstanceResourceGranularity sets a CPU granularity and FunctionDetails.getResources().getCpu() is 0, negative, or not an exact multiple of that granularity.

Common situations: Tenant submits cpu=0.35 with granularity 0.5; resources left unset so cpu=0 while a granularity is configured; CPU set in cores while granularity is expressed in fractional values whose milli-core rounding makes the modulo fail (e.g. 0.1*1000 rounding issues); migrating functions from a cluster without granularity limits to one with them.

Related errors


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