apache/beam · error · NullPointerException

Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIM

Error message

Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIMESTAMP mode is selected

What it means

For READ_TIMESTAMP or MIN_READ_TIMESTAMP modes, getTimestampBound() must parse a timestamp string into com.google.cloud.Timestamp to build the bound. This NullPointerException is thrown when readTimestamp is null, since there is no timestamp to bind the read to.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerTransformRegistrar.java:211

          case STRONG:
            return TimestampBound.strong();
          case MAX_STALENESS:
          case EXACT_STALENESS:
            if (staleness == null) {
              throw new NullPointerException(
                  "Staleness value cannot be empty when MAX_STALENESS or EXACT_STALENESS mode is selected");
            }
            if (timeUnit == null) {
              throw new NullPointerException(
                  "Time unit cannot be null when MAX_STALENESS or EXACT_STALENESS mode is selected");
            }
            return mode == MAX_STALENESS
                ? TimestampBound.ofMaxStaleness(staleness, TimeUnit.valueOf(timeUnit))
                : TimestampBound.ofExactStaleness(staleness, TimeUnit.valueOf(timeUnit));
          case READ_TIMESTAMP:
          case MIN_READ_TIMESTAMP:
            if (readTimestamp == null) {
              throw new NullPointerException(
                  "Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIMESTAMP mode is selected");
            }
            return mode == READ_TIMESTAMP
                ? TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp(readTimestamp))
                : TimestampBound.ofMinReadTimestamp(Timestamp.parseTimestamp(readTimestamp));
          default:
            throw new IllegalArgumentException("Unknown timestamp bound mode: " + mode);
        }
      }

      public ReadOperation getReadOperation() {
        if (sql != null && table != null) {
          throw new IllegalStateException(
              "Query and table params are mutually exclusive. Set just one of them.");
        }
        ReadOperation readOperation = ReadOperation.create();
        if (sql != null) {
          return readOperation.withQuery(sql);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Provide a valid RFC 3339 timestamp, e.g. .withReadTimestamp("2026-01-01T00:00:00Z").
  2. If a fixed timestamp is not needed, use STRONG or staleness modes instead.
  3. Validate the parameter is non-null and parseable with Timestamp.parseTimestamp before building.

Example fix

// before
.withTimestampBoundMode("MIN_READ_TIMESTAMP")
// after
.withTimestampBoundMode("MIN_READ_TIMESTAMP").withReadTimestamp("2026-01-01T00:00:00Z")
Defensive patterns

Strategy: validation

Validate before calling

if ((mode == TimestampBoundMode.READ_TIMESTAMP || mode == TimestampBoundMode.MIN_READ_TIMESTAMP) && readTimestamp == null) { throw new IllegalArgumentException(mode + " requires a read timestamp"); }

Try / catch

try { Timestamp.parseTimestamp(readTimestamp); } catch (NullPointerException | IllegalArgumentException e) { throw new ConfigException("readTimestamp missing or unparseable for mode " + mode, e); }

Prevention

When it happens

Trigger: Setting mode to READ_TIMESTAMP or MIN_READ_TIMESTAMP without calling withReadTimestamp(...), or the readTimestamp field absent/null in the external configuration map.

Common situations: Configs that set the mode but forgot the timestamp value; timestamps injected from upstream job parameters that were optional and empty; users confusing this mode with staleness modes and omitting the field on purpose.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/89c4df5adc5c59dd. Report an issue: GitHub.