{"id":"13fc871015a27ce7","repo":"apache/kafka","slug":"invalid-negative-offset-13fc87","errorCode":null,"errorMessage":"Invalid negative offset","messagePattern":"Invalid negative offset","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java","lineNumber":55,"sourceCode":"     * @param offset The offset\n     * @param timestamp The timestamp\n     * @throws IllegalArgumentException If the offset or timestamp is negative\n     */\n    public OffsetAndTimestamp(long offset, long timestamp) {\n        this(offset, timestamp, Optional.empty());\n    }\n\n    /**\n     * Constructs a new OffsetAndTimestamp with the given offset, timestamp, and leader epoch.\n     *\n     * @param offset The offset\n     * @param timestamp The timestamp\n     * @param leaderEpoch The leader epoch\n     * @throws IllegalArgumentException If the offset or timestamp is negative\n     */\n    public OffsetAndTimestamp(long offset, long timestamp, Optional<Integer> leaderEpoch) {\n        if (offset < 0)\n            throw new IllegalArgumentException(\"Invalid negative offset\");\n\n        if (timestamp < 0)\n            throw new IllegalArgumentException(\"Invalid negative timestamp\");\n\n        this.offset = offset;\n        this.timestamp = timestamp;\n        this.leaderEpoch = leaderEpoch;\n    }\n\n    /**\n     * Returns the timestamp.\n     *\n     * @return The timestamp\n     */\n    public long timestamp() {\n        return timestamp;\n    }\n","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java#L37-L73","documentation":"IllegalArgumentException from the OffsetAndTimestamp constructor when offset is negative. This wrapper represents a broker-resolved offset for a requested timestamp; offsets must be non-negative, so a negative value is a programming error rather than valid input.","triggerScenarios":"Calling new OffsetAndTimestamp(offset, timestamp, leaderEpoch) (or the 2-arg overload) with a negative offset, typically because a caller synthesized the result instead of using offsetsForTimes output.","commonSituations":"Custom wrappers around offsetsForTimes that pass a sentinel offset; mapping an unfound timestamp (which should yield null, not a constructed object) into OffsetAndTimestamp; arithmetic bugs producing a negative offset.","solutions":["Do not construct OffsetAndTimestamp when offsetsForTimes returned null for a partition; propagate null instead.","Validate offset >= 0 before construction; if unavailable, skip or signal 'not found' upstream.","Fix the source producing the negative value (e.g. subtracting past zero in offset arithmetic)."],"exampleFix":"// before\nOffsetAndTimestamp ot = new OffsetAndTimestamp(-1L, ts);\n\n// after\nOffsetAndTimestamp ot = brokerResult != null ? brokerResult : null;","handlingStrategy":"validation","validationCode":"// OffsetAndTimestamp requires offset >= 0\nif (offset < 0) {\n    throw new IllegalArgumentException(\"OffsetAndTimestamp offset must be >= 0 (got \" + offset + \")\");\n}\nnew OffsetAndTimestamp(offset, timestamp, leaderEpoch);","typeGuard":null,"tryCatchPattern":"try {\n    new OffsetAndTimestamp(offset, timestamp, leaderEpoch);\n} catch (IllegalArgumentException e) {\n    if (\"Invalid negative offset\".equals(e.getMessage())) {\n        // offsetsForTimes returned nothing meaningful; skip this partition\n    }\n    throw e;\n}","preventionTips":["Only construct OffsetAndTimestamp from results of consumer.offsetsForTimes() which never yield negatives.","Validate offsets coming from external stores before wrapping them in OffsetAndTimestamp.","Treat a negative offset as a corrupted-result signal from a custom timestamp lookup."],"tags":["consumer","offset","timestamp","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}