apache/beam · error · IllegalArgumentException
Empty timestamp.
Error message
Empty timestamp.
What it means
parseTimestampAsMsSinceEpoch converts a timestamp attribute string to epoch millis. An empty attribute value cannot be parsed as a timestamp, so an IllegalArgumentException is thrown immediately rather than attempting numeric or RFC 3339 parsing.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubClient.java:87
PubsubOptions options,
@Nullable String rootUrlOverride)
throws IOException;
PubsubClient newClient(
@Nullable String timestampAttribute, @Nullable String idAttribute, PubsubOptions options)
throws IOException;
/** Return the display name for this factory. Eg "Json", "gRPC". */
String getKind();
}
/**
* Return timestamp as ms-since-unix-epoch corresponding to {@code timestamp}. Throw {@link
* IllegalArgumentException} if timestamp cannot be recognized.
*/
protected static long parseTimestampAsMsSinceEpoch(String timestamp) {
if (timestamp.isEmpty()) {
throw new IllegalArgumentException("Empty timestamp.");
}
try {
// Try parsing as milliseconds since epoch. Note there is no way to parse a
// string in RFC 3339 format here.
// Expected IllegalArgumentException if parsing fails; we use that to fall back
// to RFC 3339.
return Long.parseLong(timestamp);
} catch (IllegalArgumentException e1) {
// Try parsing as RFC3339 string. DateTime.parseRfc3339 will throw an
// IllegalArgumentException if parsing fails, and the caller should handle.
return DateTime.parseRfc3339(timestamp).getValue();
}
}
/**
* Return the timestamp (in ms since unix epoch) to use for a Pubsub message with {@code
* timestampAttribute} and {@code attributes}.
*View on GitHub (pinned to 12126d8942)
Solutions
- Fix the producer to emit a valid millisecond-epoch or RFC 3339 timestamp value
- Skip or drop messages whose timestamp attribute is empty in an earlier transform
- Use Pub/Sub server-side publishTime (omit timestampAttribute) instead of a custom attribute
- Guard the attribute at publish time: only set it when a non-empty value is available
Example fix
// before
attributes.put("event_time", maybeNullTimestamp == null ? "" : maybeNullTimestamp);
// after
if (maybeNullTimestamp != null) {
attributes.put("event_time", Long.toString(maybeNullTimestamp));
} Defensive patterns
Strategy: validation
Validate before calling
if (timestampAttr == null || timestampAttr.isEmpty()) {
throw new IllegalArgumentException("timestamp attribute must be a non-empty epoch-millis or RFC3339 string");
}
Long.parseLong(timestampAttr); // sanity check Type guard
boolean validTimestamp(String ts) { return ts != null && !ts.isEmpty() && (ts.matches("\\d+") || isValidRfc3339(ts)); } Try / catch
try { long ts = parseTimestampAsMsSinceEpoch(attr); } catch (IllegalArgumentException e) { /* fall back to publishTime or drop message */ } Prevention
- Never publish empty timestamp attribute values; omit the attribute instead
- Prefer server publishTime when no reliable custom attribute exists
- Contract-test producers for the timestamp attribute format
- Validate attributes at the producer boundary
When it happens
Trigger: PubsubIO.read with a timestampAttribute configured; a pulled message contains the timestamp attribute but its value is the empty string; extractTimestampAttribute delegates to parseTimestampAsMsSinceEpoch.
Common situations: Producers writing the attribute with an empty value (e.g. empty env var or missing field rendered as ""); attribute set but never populated; upstream system clearing the field.
Related errors
- Received message missing publishTime
- Dropping output field '{}' before writing to PubSub because
- Extract file timestamp failed: got file timestamp == 0.
- Unable to parse JSON value
- micros_instant logical type encountered a Java Instant with
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/f479c1607dd352a7.
Report an issue: GitHub.