apache/seatunnel · error · IllegalArgumentException

start_timestamp can't be negative

Error message

start_timestamp can't be negative

What it means

The time-range validation in HbaseClient.applyTimeRange rejects a start_timestamp option that is negative, throwing IllegalArgumentException('start_timestamp can't be negative'). HBase timestamp ranges are epoch millis and must be non-negative, so the library fails fast before building the Scan. This is a config validation error, not a runtime I/O failure.

Source

Thrown at seatunnel-connectors-v2/connector-hbase/src/main/java/org/apache/seatunnel/connectors/seatunnel/hbase/client/HbaseClient.java:404

        scan.setCaching(hbaseParameters.getCaching());
        scan.setBatch(hbaseParameters.getBatch());
        for (String columnName : columnNames) {
            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

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set start_timestamp to a valid epoch-millisecond value >= 0
  2. Check how the value is computed/templated in your job config (e.g. Unix ts * 1000)
  3. Remove start_timestamp if you do not need a lower time bound (defaults to 0)

Example fix

// before
start_timestamp = -1000
// after
start_timestamp = 1700000000000
Defensive patterns

Strategy: validation

Validate before calling

Long start = config.getStartTimestamp();
if (start != null && start < 0) {
    throw new IllegalArgumentException("start_timestamp must be >= 0 (epoch millis)");
}

Type guard

static boolean validStartTimestamp(Long ts) { return ts == null || ts >= 0; }

Try / catch

try { client.buildScan(params); }
catch (IllegalArgumentException e) {
    if (e.getMessage().contains("start_timestamp")) {
        // fix config to a non-negative epoch-millis value
    } else throw e;
}

Prevention

When it happens

Trigger: Configuring source/sink option start_timestamp with a negative value (e.g. -1 or a misparsed epoch in milliseconds) that reaches buildScan via applyTimeRange.

Common situations: Passing a timestamp in seconds or as a signed relative offset instead of epoch millis; template placeholder unresolved to -1; copy-paste typo.

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/eade82a667244c58. Report an issue: GitHub.