{"record":{"id":"0d8c0b0481ca3d8a","repo":"apache/beam","slug":"staleness-value-cannot-be-empty-when-max-staleness-or-exact","errorCode":null,"errorMessage":"Staleness value cannot be empty when MAX_STALENESS or EXACT_STALENESS mode is selected","messagePattern":"Staleness value cannot be empty when MAX_STALENESS or EXACT_STALENESS mode is selected","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerTransformRegistrar.java","lineNumber":198,"sourceCode":"        this.timeUnit = timeUnit;\n      }\n\n      public void setStaleness(@Nullable Long staleness) {\n        this.staleness = staleness;\n      }\n\n      private @Nullable TimestampBound getTimestampBound() {\n        if (timestampBoundMode == null) {\n          return null;\n        }\n        TimestampBound.Mode mode = TimestampBound.Mode.valueOf(timestampBoundMode);\n        switch (mode) {\n          case STRONG:\n            return TimestampBound.strong();\n          case MAX_STALENESS:\n          case EXACT_STALENESS:\n            if (staleness == null) {\n              throw new NullPointerException(\n                  \"Staleness value cannot be empty when MAX_STALENESS or EXACT_STALENESS mode is selected\");\n            }\n            if (timeUnit == null) {\n              throw new NullPointerException(\n                  \"Time unit cannot be null when MAX_STALENESS or EXACT_STALENESS mode is selected\");\n            }\n            return mode == MAX_STALENESS\n                ? TimestampBound.ofMaxStaleness(staleness, TimeUnit.valueOf(timeUnit))\n                : TimestampBound.ofExactStaleness(staleness, TimeUnit.valueOf(timeUnit));\n          case READ_TIMESTAMP:\n          case MIN_READ_TIMESTAMP:\n            if (readTimestamp == null) {\n              throw new NullPointerException(\n                  \"Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIMESTAMP mode is selected\");\n            }\n            return mode == READ_TIMESTAMP\n                ? TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp(readTimestamp))\n                : TimestampBound.ofMinReadTimestamp(Timestamp.parseTimestamp(readTimestamp));","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerTransformRegistrar.java#L180-L216","documentation":"getTimestampBound() builds a Cloud Spanner TimestampBound for stale reads based on the configured read mode. When the mode is MAX_STALENESS or EXACT_STALENESS, both a staleness numeric value and a time unit are required; this NullPointerException is thrown when staleness is null, because Spanner's ofMaxStaleness/ofExactStaleness cannot be invoked without a duration.","triggerScenarios":"Setting read mode to MAX_STALENESS or EXACT_STALENESS (e.g. withReadTime(\"MAX_STALENESS\") or via external configuration) but leaving the staleness value unset/null in the ReadBuilder/ChangeStreamReaderBuilder configuration.","commonSituations":"YAML/JSON external pipeline specs that set the mode but omit the staleness field; CLI options where the staleness flag was not passed; defaults where mode changed to staleness-based without updating the value.","solutions":["Provide the staleness value together with the mode (e.g. staleness=10, timeUnit=SECONDS).","If you don't want stale reads, switch the mode to STRONG instead.","Add a pre-build check that (mode==MAX_STALENESS||mode==EXACT_STALENESS) implies staleness!=null."],"exampleFix":"// before\n.withTimestampBoundMode(\"MAX_STALENESS\")\n// after\n.withTimestampBoundMode(\"MAX_STALENESS\").withStaleness(10).withTimeUnit(\"SECONDS\")","handlingStrategy":"validation","validationCode":"if ((mode == TimestampBoundMode.MAX_STALENESS || mode == TimestampBoundMode.EXACT_STALENESS) && staleness == null) { throw new IllegalArgumentException(mode + \" requires a staleness value\"); }","typeGuard":null,"tryCatchPattern":"try { TimestampBound tb = config.timestampBound(); } catch (NullPointerException e) { throw new ConfigException(\"staleness/timeUnit/readTimestamp missing for mode \" + config.mode, e); }","preventionTips":["Model staleness as a required field whenever the mode is staleness-based (schema-level validation).","Default to STRONG mode when no staleness is configured.","Validate the full (mode, staleness, timeUnit) triple before building the transform."],"tags":["java","apache-beam","google-cloud-spanner","null-check","staleness"],"backgroundTag":"null-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}