shuzheng/zheng · critical · RuntimeException
Clock moved backwards. Refusing to generate id for %d milli
Error message
Clock moved backwards. Refusing to generate id for %d milliseconds
What it means
nextId() compares the current timestamp with lastTimestamp; if time has gone backwards it throws RuntimeException refusing to generate ids for the negative interval, because reusing a timestamp could produce duplicate snowflake ids. The message includes how many milliseconds the clock moved backwards.
Source
Thrown at zheng-common/src/main/java/com/zheng/common/util/key/SnowflakeIdWorker.java:118
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
// ==============================Methods==========================================
/**
* 获得下一个ID (该方法是线程安全的)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}
//上次生成ID的时间截View on GitHub (pinned to 7005c0a775)
Solutions
- Fix the underlying clock source and let it catch up; the service will resume once current time exceeds lastTimestamp.
- Enable gradual (slew) NTP corrections instead of step changes (e.g. ntpd without -g steps, chrony slew mode).
- Restart the service only if the clock regression is permanent and ensure workerId/datacenterId differs, or persist lastTimestamp and reject duplicates on restart.
- Wrap id generation so the RuntimeException is handled: queue requests briefly or fail over to another node whose clock is monotonic.
Example fix
// before
long id = idWorker.nextId(); // throws after clock rollback
// after
try {
long id = idWorker.nextId();
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Clock moved backwards")) {
// wait for clock to catch up or fail over
} else {
throw e;
}
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check before generating
long ts = System.currentTimeMillis();
// if a previously persisted lastTimestamp is newer than ts, clock regressed
if (ts < lastKnownTimestamp) {
log.warn("Clock moved backwards by {} ms; delaying id generation", lastKnownTimestamp - ts);
} Type guard
boolean clockIsMonotonic(long lastTimestamp) {
return System.currentTimeMillis() >= lastTimestamp;
} Try / catch
long id;
while (true) {
try { id = idWorker.nextId(); break; }
catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Clock moved backwards")) {
Thread.sleep(100); // wait for clock to catch up
} else throw e;
}
} Prevention
- Run NTP/chrony in slew mode so clocks never step backwards.
- Never restore VM snapshots of machines running id generators without resetting worker state.
- Persist lastTimestamp and refuse to serve ids after rollback until time catches up.
- Monitor clock offsets (e.g. chrony tracking) and alert on negative adjustments.
- Isolate id generation on nodes with stable clocks (dedicated, non-preemptible VMs).
When it happens
Trigger: Calling nextId() after the system clock was set back (manual change, NTP correction, VM snapshot restore, leap adjustment) so timeGen() returns a value smaller than the previously used lastTimestamp.
Common situations: VM/host restored from snapshot; NTP daemon stepping the clock backwards; container migrated to a host with skewed clock; operator manually correcting a too-fast clock.
Related errors
- worker Id can't be greater than %d or less than 0
- datacenter Id can't be greater than %d or less than 0
AI-assisted analysis of shuzheng/zheng@7005c0a775 (2026-09-04).
Data as JSON: /api/errors/d454b950784e88f9.
Report an issue: GitHub.