apache/beam · error · NullPointerException

Time unit cannot be null when MAX_STALENESS or EXACT_STALENE

Error message

Time unit cannot be null when MAX_STALENESS or EXACT_STALENESS mode is selected

What it means

getTimestampBound() requires a TimeUnit whenever the Spanner read mode is MAX_STALENESS or EXACT_STALENESS; the staleness number alone is not a duration. This NullPointerException is thrown when timeUnit is null, because TimestampBound.ofMaxStaleness/ofExactStaleness needs (long, TimeUnit).

Source

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

        this.staleness = staleness;
      }

      private @Nullable TimestampBound getTimestampBound() {
        if (timestampBoundMode == null) {
          return null;
        }
        TimestampBound.Mode mode = TimestampBound.Mode.valueOf(timestampBoundMode);
        switch (mode) {
          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);
        }
      }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Call .withTimeUnit("SECONDS") (or another valid java.util.concurrent.TimeUnit name) alongside the staleness value.
  2. Verify the unit string is a valid TimeUnit enum constant (NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS).
  3. Use STRONG mode if you don't need bounded staleness.

Example fix

// before
.withTimestampBoundMode("EXACT_STALENESS").withStaleness(15)
// after
.withTimestampBoundMode("EXACT_STALENESS").withStaleness(15).withTimeUnit("SECONDS")
Defensive patterns

Strategy: validation

Validate before calling

if ((mode == TimestampBoundMode.MAX_STALENESS || mode == TimestampBoundMode.EXACT_STALENESS) && timeUnit == null) { throw new IllegalArgumentException(mode + " requires a TimeUnit"); }

Try / catch

try { TimeUnit u = TimeUnit.valueOf(config.getTimeUnit()); } catch (NullPointerException | IllegalArgumentException e) { throw new ConfigException("Invalid or missing timeUnit: " + config.getTimeUnit(), e); }

Prevention

When it happens

Trigger: Setting mode MAX_STALENESS or EXACT_STALENESS with a staleness value but no time unit (withTimeUnit not called, or the timeUnit field missing/blank in external configuration).

Common situations: Config files where staleness was added as "10" but the unit key was forgotten; programmatic builders copying another mode's setup; invalid unit strings would also fail later at TimeUnit.valueOf, so ensure exact JDK unit names.

Related errors


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