{"id":"57622e221e3b63b9","repo":"apache/kafka","slug":"invalid-timestamp-d-timestamp-should-always-be","errorCode":null,"errorMessage":"Invalid timestamp: %d. Timestamp should always be non-negative or null.","messagePattern":"Invalid timestamp: (.+?)\\. Timestamp should always be non-negative or null\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java","lineNumber":75,"sourceCode":"    private final V value;\n    private final Long timestamp;\n\n    /**\n     * Creates a record with a specified timestamp to be sent to a specified topic and partition\n     * \n     * @param topic The topic the record will be appended to\n     * @param partition The partition to which the record should be sent\n     * @param timestamp The timestamp of the record, in milliseconds since epoch. If null, the producer will assign\n     *                  the timestamp using System.currentTimeMillis().\n     * @param key The key that will be included in the record\n     * @param value The record contents\n     * @param headers the headers that will be included in the record\n     */\n    public ProducerRecord(String topic, Integer partition, Long timestamp, K key, V value, Iterable<Header> headers) {\n        if (topic == null)\n            throw new IllegalArgumentException(\"Topic cannot be null.\");\n        if (timestamp != null && timestamp < 0)\n            throw new IllegalArgumentException(\n                    String.format(\"Invalid timestamp: %d. Timestamp should always be non-negative or null.\", timestamp));\n        if (partition != null && partition < 0)\n            throw new IllegalArgumentException(\n                    String.format(\"Invalid partition: %d. Partition number should always be non-negative or null.\", partition));\n        this.topic = topic;\n        this.partition = partition;\n        this.key = key;\n        this.value = value;\n        this.timestamp = timestamp;\n        this.headers = new RecordHeaders(headers);\n    }\n\n    /**\n     * Creates a record with a specified timestamp to be sent to a specified topic and partition\n     *\n     * @param topic The topic the record will be appended to\n     * @param partition The partition to which the record should be sent\n     * @param timestamp The timestamp of the record, in milliseconds since epoch. If null, the producer will assign the","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java#L57-L93","documentation":"Thrown by the ProducerRecord constructor when a non-null timestamp is negative. The producer accepts either null (it will stamp the record with current time) or a non-negative millisecond epoch value; a negative value would produce an invalid record timestamp and is rejected at construction with an IllegalArgumentException.","triggerScenarios":"Calling any ProducerRecord constructor that takes a Long timestamp with a negative value, e.g. new ProducerRecord<>(topic, partition, -1L, key, value). Also when the timestamp is derived from System.currentTimeMillis() under a clock skew or mock clock returning negative values, or from a domain field that was never validated and was set to -1 as a sentinel.","commonSituations":"Using -1L or 0L-minus-one as a 'no timestamp' sentinel instead of null; consuming a timestamp from an upstream system (e.g. CDC, database column) that uses 0 or negative for missing values; testing with a mocked Time/ Clock that returns negative millis; clock skew on misconfigured VMs or containers where System.currentTimeMillis() is unreliable.","solutions":["Pass null instead of a negative sentinel when you have no timestamp; the producer will assign System.currentTimeMillis() for you.","Sanitize upstream timestamps before construction: long ts = sourceTs != null && sourceTs >= 0 ? sourceTs : null; then build the ProducerRecord.","If using a custom/mock clock in tests, ensure it returns a non-negative epoch millis value, or inject null for the timestamp in test fixtures."],"exampleFix":"// before\nlong ts = event.getEventTime(); // returns -1 when unknown\nnew ProducerRecord<>(topic, partition, ts, key, value);\n\n// after\nLong ts = event.getEventTime();\nif (ts != null && ts < 0) ts = null;\nnew ProducerRecord<>(topic, partition, ts, key, value);","handlingStrategy":"validation","validationCode":"// Timestamp must be null or >= 0 (ms since epoch).\nLong timestamp = /* source timestamp */;\nif (timestamp != null && timestamp < 0L) {\n    throw new IllegalArgumentException(\"timestamp must be non-negative or null, got \" + timestamp);\n}\nProducerRecord<K, V> record = new ProducerRecord<>(topic, partition, timestamp, key, value);","typeGuard":"// Narrows a Long to a valid producer timestamp (null OR non-negative).\nstatic Long requireValidTimestamp(Long ts) {\n    if (ts != null && ts < 0L) throw new IllegalArgumentException(\"negative timestamp: \" + ts);\n    return ts;\n}","tryCatchPattern":"try {\n    ProducerRecord<K, V> r = new ProducerRecord<>(topic, partition, timestamp, key, value);\n    producer.send(r);\n} catch (IllegalArgumentException e) {\n    // Either drop the record or re-stamp with System.currentTimeMillis() and retry build\n}","preventionTips":["Prefer passing null (let the producer stamp it) unless you have a real event-time source.","When sourcing timestamps from external systems, sanitize: clamp negatives to null, not to 0.","Guard clock extraction (e.g. parsing failures returning -1) before building the record.","Unit-test the record-building layer with boundary inputs (-1L, 0L, now, null)."],"tags":["kafka","java","producer","validation","timestamp"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}