apache/seatunnel · error · IllegalArgumentException
end_timestamp can't be negative
Error message
end_timestamp can't be negative
What it means
The time-range validation in HbaseClient.applyTimeRange rejects a negative end_timestamp, throwing IllegalArgumentException('end_timestamp can't be negative'). HBase time ranges are epoch millis and must be non-negative. The library fails fast during Scan construction rather than sending an invalid range to the cluster.
Source
Thrown at seatunnel-connectors-v2/connector-hbase/src/main/java/org/apache/seatunnel/connectors/seatunnel/hbase/client/HbaseClient.java:407
String[] columnNameSplit = columnName.split(":");
scan.addColumn(Bytes.toBytes(columnNameSplit[0]), Bytes.toBytes(columnNameSplit[1]));
}
return scan;
}
private static void applyTimeRange(Scan scan, HbaseParameters hbaseParameters)
throws IOException {
Long startTimestamp = hbaseParameters.getStartTimestamp();
Long endTimestamp = hbaseParameters.getEndTimestamp();
if (startTimestamp == null && endTimestamp == null) {
return;
}
if (startTimestamp != null && startTimestamp < 0) {
throw new IllegalArgumentException("start_timestamp can't be negative");
}
if (endTimestamp != null && endTimestamp < 0) {
throw new IllegalArgumentException("end_timestamp can't be negative");
}
long min = startTimestamp == null ? 0L : startTimestamp;
long max = endTimestamp == null ? Long.MAX_VALUE : endTimestamp;
if (min >= max) {
throw new IllegalArgumentException("start_timestamp must be less than end_timestamp");
}
scan.setTimeRange(min, max);
}
/**
* Get a RegionLocator.
*
* @param tableName table name (preferably fully qualified as {@code namespace:table})
* @return RegionLocator
* @throws IOException exception
* @deprecated Use {@link #getRegionLocator(String, String)} instead to avoid relying on the
* default namespace behavior.View on GitHub (pinned to cf67b549a7)
Solutions
- Set end_timestamp to a valid epoch-millisecond value >= 0
- Verify the expression that generates the value in your config or scheduler
- Omit end_timestamp to default to Long.MAX_VALUE (no upper bound)
Example fix
// before end_timestamp = -1 // after end_timestamp = 1700003600000
Defensive patterns
Strategy: validation
Validate before calling
Long end = config.getEndTimestamp();
if (end != null && end < 0) {
throw new IllegalArgumentException("end_timestamp must be >= 0 (epoch millis)");
} Type guard
static boolean validEndTimestamp(Long ts) { return ts == null || ts >= 0; } Try / catch
try { client.buildScan(params); }
catch (IllegalArgumentException e) {
if (e.getMessage().contains("end_timestamp")) {
// correct the config value before resubmitting
} else throw e;
} Prevention
- Compute end times carefully to avoid negative offsets
- Use epoch milliseconds consistently
- Omit end_timestamp when no upper bound is needed
When it happens
Trigger: Configuring option end_timestamp with a negative value that reaches buildScan via applyTimeRange.
Common situations: Computing end time as now-minus-offset with a sign error; seconds-vs-millis confusion producing overflow/negatives; placeholder substitution failure.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- start_timestamp can't be negative
- start_timestamp must be less than end_timestamp
- startRowkey can't be bigger than endRowkey
- start_mode.timestamp must not be greater than the current ti
- start_mode.end_timestamp must not be greater than the curren
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/03b81535d4b32904.
Report an issue: GitHub.