{"record":{"id":"89c4df5adc5c59dd","repo":"apache/beam","slug":"timestamp-cannot-be-null-when-read-timestamp-or-min-read","errorCode":null,"errorMessage":"Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIMESTAMP mode is selected","messagePattern":"Timestamp cannot be null when READ_TIMESTAMP or MIN_READ_TIMESTAMP 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":211,"sourceCode":"          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));\n          default:\n            throw new IllegalArgumentException(\"Unknown timestamp bound mode: \" + mode);\n        }\n      }\n\n      public ReadOperation getReadOperation() {\n        if (sql != null && table != null) {\n          throw new IllegalStateException(\n              \"Query and table params are mutually exclusive. Set just one of them.\");\n        }\n        ReadOperation readOperation = ReadOperation.create();\n        if (sql != null) {\n          return readOperation.withQuery(sql);","sourceCodeStart":193,"sourceCodeEnd":229,"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#L193-L229","documentation":"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.","triggerScenarios":"Setting mode to READ_TIMESTAMP or MIN_READ_TIMESTAMP without calling withReadTimestamp(...), or the readTimestamp field absent/null in the external configuration map.","commonSituations":"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.","solutions":["Provide a valid RFC 3339 timestamp, e.g. .withReadTimestamp(\"2026-01-01T00:00:00Z\").","If a fixed timestamp is not needed, use STRONG or staleness modes instead.","Validate the parameter is non-null and parseable with Timestamp.parseTimestamp before building."],"exampleFix":"// before\n.withTimestampBoundMode(\"MIN_READ_TIMESTAMP\")\n// after\n.withTimestampBoundMode(\"MIN_READ_TIMESTAMP\").withReadTimestamp(\"2026-01-01T00:00:00Z\")","handlingStrategy":"validation","validationCode":"if ((mode == TimestampBoundMode.READ_TIMESTAMP || mode == TimestampBoundMode.MIN_READ_TIMESTAMP) && readTimestamp == null) { throw new IllegalArgumentException(mode + \" requires a read timestamp\"); }","typeGuard":null,"tryCatchPattern":"try { Timestamp.parseTimestamp(readTimestamp); } catch (NullPointerException | IllegalArgumentException e) { throw new ConfigException(\"readTimestamp missing or unparseable for mode \" + mode, e); }","preventionTips":["Parse and validate the timestamp at config-load time, not at transform-build time.","Use ISO-8601/RFC 3339 format (e.g. 2026-01-01T00:00:00Z).","Fall back to STRONG mode when no timestamp is provided."],"tags":["java","apache-beam","google-cloud-spanner","null-check","timestamp"],"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"}