{"record":{"id":"e9056d057a331bca","repo":"apache/pulsar","slug":"per-instance-cpu-requested-s-ram-requested-s","errorCode":null,"errorMessage":"Per instance cpu requested, %s, ram requested, %s, for function should be positive and the same multiple of the granularity, cpu, %s, ram, %s","messagePattern":"Per instance cpu requested, (.+?), ram requested, (.+?), for function should be positive and the same multiple of the granularity, cpu, (.+?), ram, (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java","lineNumber":529,"sourceCode":"                                        functionDetails.getResources().getCpu(), grnCpu));\n                    }\n                    if (functionInstanceResourceChangeInLockStep) {\n                        multiples = cpuMillis / grnCpuMillis;\n                    }\n                }\n            }\n            if (grnRam != null && grnRam > 0) {\n                if (functionDetails.getResources().getRam() == 0\n                        || functionDetails.getResources().getRam() % grnRam != 0) {\n                    throw new IllegalArgumentException(\n                            String.format(\"Per instance ram requested, %s, \"\n                                            + \"for function should be positive and a multiple of the granularity, %s\",\n                                    functionDetails.getResources().getRam(), grnRam));\n                }\n                if (functionInstanceResourceChangeInLockStep && multiples > 0) {\n                    long ramMultiples = functionDetails.getResources().getRam() / grnRam;\n                    if (multiples != ramMultiples) {\n                        throw new IllegalArgumentException(\n                                String.format(\"Per instance cpu requested, %s, ram requested, %s,\"\n                                                + \" for function should be positive and the same multiple of the \"\n                                                + \"granularity, cpu, %s, ram, %s\",\n                                        functionDetails.getResources().getCpu(),\n                                        functionDetails.getResources().getRam(), grnCpu, grnRam));\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public Optional<KubernetesFunctionAuthProvider> getAuthProvider() {\n        return authProvider;\n    }\n\n    @Override\n    public Optional<KubernetesManifestCustomizer> getRuntimeCustomizer() {","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java#L511-L547","documentation":"When functionInstanceResourceChangeInLockStep is enabled, CPU and RAM must scale together: the multiples of their respective granularities must be identical. KubernetesRuntimeFactory computes cpu multiples and ramMultiples during admission; if they differ, doAdmissionChecks throws this IllegalArgumentException.","triggerScenarios":"Submitting/updating a function with lock-step resource changes enabled where cpu/grnCpu != ram/grnRam — e.g. cpu=1.0 (2 multiples of 0.5) with ram=1GB (1 multiple of 1GB).","commonSituations":"Scaling cpu and ram independently while functionInstanceResourceChangeInLockStep=true; adjusting only one resource during a function update; provisioning bundles sized by different rules for cpu and memory.","solutions":["Set cpu and ram so that both are the SAME multiple of their granularities (e.g. 2x cpu granularity and 2x ram granularity).","Disable functionInstanceResourceChangeInLockStep in the worker config if independent cpu/ram scaling is intended.","Increase cpu and ram proportionally when scaling a function instance up or down.","Verify both resources after every update; the check runs on each doAdmissionChecks pass."],"exampleFix":"// before (granularity cpu=0.5, ram=1GB, lockStep=true)\nresources:\n  cpu: 1.0   # 2 multiples\n  ram: 1GB   # 1 multiple\n// after\nresources:\n  cpu: 1.0   # 2 multiples\n  ram: 2GB   # 2 multiples","handlingStrategy":"validation","validationCode":"long cpuMultiples = Math.round(1000 * resources.getCpu()) / Math.round(1000 * grnCpu);\nlong ramMultiples = resources.getRam() / grnRam;\nif (lockStepEnabled && cpuMultiples != ramMultiples) {\n    throw new IllegalArgumentException(\"cpu and ram must be the same multiple of their granularities\");\n}","typeGuard":"boolean isLockStepConsistent(double cpu, long ramBytes, double grnCpu, long grnRam) {\n    long cpuM = Math.round(1000 * cpu) / Math.round(1000 * grnCpu);\n    long ramM = ramBytes / grnRam;\n    return cpuM == ramM;\n}","tryCatchPattern":null,"preventionTips":["Scale cpu and ram together (same multiple count) when lock-step mode is on.","Disable functionInstanceResourceChangeInLockStep if independent scaling is a requirement.","Re-validate resources after every function update; admission checks run each time."],"tags":["pulsar-functions","kubernetes","resource-validation","configuration"],"backgroundTag":"resource-granularity-violation","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}