apache/beam · error · IllegalArgumentException
'max-past' must be a positive long value.
Error message
'max-past' must be a positive long value.
What it means
For TIMESTAMP fields, the optional 'fields.<name>.max-past' property controls how far back in the past random timestamps may fall. It must parse to a strictly positive long (milliseconds). Zero or negative values throw an IllegalArgumentException.
Solutions
- Set 'max-past' to a positive integer millisecond value (e.g. 600000 for 10 minutes).
- Remove the 'max-past' property entirely to use the default (Instant.now()).
- Convert duration strings to milliseconds before writing the property.
Example fix
// before
'{"fields":{"ts":{"max-past":0}}}'
// after
'{"fields":{"ts":{"max-past":600000}}}' Defensive patterns
Strategy: validation
Validate before calling
JsonNode p = props.path("fields." + name + ".max-past");
if (!p.isMissingNode() && p.asLong() <= 0) {
throw new IllegalArgumentException("max-past must be > 0");
} Try / catch
try { buildRowFn(props); } catch (IllegalArgumentException e) { /* remove or correct max-past */ } Prevention
- Use positive millisecond integers only.
- Remove the key instead of setting 0 to use defaults.
When it happens
Trigger: Setting fields.<name>.max-past to 0, a negative number, or a non-numeric value that asLong coerces to <= 0, on a TIMESTAMP datagen field.
Common situations: Configuring max-past: 0 thinking it disables the option; using a negative duration intending 'in the past'; pasting a duration string like '5m' that Jackson coerces to 0.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- The 'sequence' generator for integers only supports integer…
- The specified 'event-time.timestamp-column
- A 'datagen' table requires either 'rows-per-second' (for…
- Configuration must provide a query string.
- Data generator requires a defined SQL type. Beam type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/a90a11905edc8031.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/datagen/DataGeneratorRowFn.java:187
return (index) -> minD + (maxD - minD) * ThreadLocalRandom.current().nextDouble();
case TINYINT:
case SMALLINT:
case INTEGER:
case BIGINT:
long minL = properties.path("fields." + fieldName + ".min").asLong(0L);
long maxL = properties.path("fields." + fieldName + ".max").asLong(Long.MAX_VALUE);
return (index) -> minL + (long) (ThreadLocalRandom.current().nextDouble() * (maxL - minL));
case DECIMAL:
double minBd = properties.path("fields." + fieldName + ".min").asDouble(0.0);
double maxBd = properties.path("fields." + fieldName + ".max").asDouble(1000.0);
return (index) ->
BigDecimal.valueOf(minBd + (maxBd - minBd) * ThreadLocalRandom.current().nextDouble());
case TIMESTAMP:
JsonNode maxPastNode = properties.path("fields." + fieldName + ".max-past");
if (!maxPastNode.isMissingNode()) {
long maxPastMs = maxPastNode.asLong();
if (maxPastMs <= 0) {
throw new IllegalArgumentException("'max-past' must be a positive long value.");
}
return (index) ->
Instant.now()
.minus(
Duration.millis(
(long) (ThreadLocalRandom.current().nextDouble() * maxPastMs)));
}
return (index) -> Instant.now();
default:
throw new UnsupportedOperationException("Unsupported SQL type for datagen: " + sqlTypeName);
}
}
}
View on GitHub (pinned to 12126d8942)