{"record":{"id":"391d0be9d525f8bb","repo":"apache/pulsar","slug":"sequencekeysdeltas-requires-at-least-one-delta","errorCode":null,"errorMessage":"SequenceKeysDeltas requires at least one delta","messagePattern":"SequenceKeysDeltas requires at least one delta","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/Option.java","lineNumber":91,"sourceCode":"     * {@code prefix-{seq0}-{seq1}-...} where each sequence is zero-padded 20-digit decimal and\n     * each dimension increments atomically by its delta.\n     *\n     * <p>The {@code Stat} returned from the {@code put} carries the actual generated path. Pair\n     * with {@link MetadataStore#subscribeSequence} to receive notifications as new sequence keys\n     * are created.\n     *\n     * <p>Constraints: {@code deltas} must be non-empty, the first delta must be {@code > 0}, and\n     * the rest must be {@code >= 0}. On Oxia a {@link PartitionKey} must also be provided.\n     * Backends without native sequence-key support synthesize the same key format using a\n     * sidecar counter document and CAS.\n     *\n     * @param deltas per-dimension increments\n     */\n    record SequenceKeysDeltas(List<Long> deltas) implements Option {\n\n        public SequenceKeysDeltas {\n            if (deltas == null || deltas.isEmpty()) {\n                throw new IllegalArgumentException(\"SequenceKeysDeltas requires at least one delta\");\n            }\n            if (deltas.get(0) <= 0) {\n                throw new IllegalArgumentException(\"first delta must be > 0, got \" + deltas.get(0));\n            }\n            for (int i = 1; i < deltas.size(); i++) {\n                if (deltas.get(i) < 0) {\n                    throw new IllegalArgumentException(\n                            \"delta at index \" + i + \" must be >= 0, got \" + deltas.get(i));\n                }\n            }\n            deltas = List.copyOf(deltas);\n        }\n    }\n}\n","sourceCodeStart":73,"sourceCodeEnd":106,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/Option.java#L73-L106","documentation":"Option.SequenceKeysDeltas is a record representing per-dimension increments for a sequence subscription; its compact constructor validates the input. It throws IllegalArgumentException('SequenceKeysDeltas requires at least one delta') when constructed with a null or empty delta list, since a sequence advance must move at least the first dimension.","triggerScenarios":"new SequenceKeysDeltas(List.of()) or new SequenceKeysDeltas(null), or programmatically building deltas from an empty collection before passing them to subscribeSequence.","commonSituations":"Code computing deltas from variable-dimension state that produced zero entries; deserializing a malformed/empty options payload; copy-paste building an empty list placeholder.","solutions":["Ensure the delta list has at least one element before constructing, e.g. guard with List.isEmpty().","Provide a default first delta (>= 1) when no dimension state is available.","Fix upstream logic that produces empty delta lists so callers never construct the option with no deltas."],"exampleFix":"// before\nOption opt = new SequenceKeysDeltas(computedDeltas); // may be empty\n// after\nif (computedDeltas == null || computedDeltas.isEmpty()) {\n    computedDeltas = List.of(1L); // minimal valid advance\n}\nOption opt = new SequenceKeysDeltas(computedDeltas);","handlingStrategy":"validation","validationCode":"if (deltas == null || deltas.isEmpty()) {\n    throw new IllegalArgumentException(\"SequenceKeysDeltas needs at least one delta\");\n}\nOption opt = new SequenceKeysDeltas(deltas);","typeGuard":"boolean validDeltas(List<Long> deltas) {\n    return deltas != null && !deltas.isEmpty() && deltas.get(0) > 0\n        && deltas.stream().skip(1).allMatch(d -> d >= 0);\n}","tryCatchPattern":"try {\n    Option opt = new SequenceKeysDeltas(deltas);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Invalid deltas: {}\", e.getMessage());\n    opt = new SequenceKeysDeltas(List.of(1L));\n}","preventionTips":["Guard delta lists for non-empty content and positive first element before constructing","Add unit tests covering empty/null delta inputs at the producer of the list","Prefer a factory method that normalizes empty input instead of raw record construction"],"tags":["pulsar-metadata","illegalargument","validation","sequence"],"backgroundTag":"invalid-argument-empty-collection","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}