{"record":{"id":"8a55dee3a0f3e826","repo":"apache/iceberg","slug":"failed-to-parse-streamingoffset-from-json-string-8a55de","errorCode":null,"errorMessage":"Failed to parse StreamingOffset from JSON string %s","messagePattern":"Failed to parse StreamingOffset from JSON string (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java","lineNumber":68,"sourceCode":"   * @param snapshotId The current processed snapshot id.\n   * @param position The position of last scanned file in snapshot.\n   * @param scanAllFiles whether to scan all files in a snapshot; for example, to read all data when\n   *     starting a stream.\n   */\n  StreamingOffset(long snapshotId, long position, boolean scanAllFiles) {\n    this.snapshotId = snapshotId;\n    this.position = position;\n    this.scanAllFiles = scanAllFiles;\n  }\n\n  static StreamingOffset fromJson(String json) {\n    Preconditions.checkNotNull(json, \"Cannot parse StreamingOffset JSON: null\");\n\n    try {\n      JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class);\n      return fromJsonNode(node);\n    } catch (IOException e) {\n      throw new UncheckedIOException(\n          String.format(\"Failed to parse StreamingOffset from JSON string %s\", json), e);\n    }\n  }\n\n  static StreamingOffset fromJson(InputStream inputStream) {\n    Preconditions.checkNotNull(inputStream, \"Cannot parse StreamingOffset from inputStream: null\");\n\n    JsonNode node;\n    try {\n      node = JsonUtil.mapper().readValue(inputStream, JsonNode.class);\n    } catch (IOException e) {\n      throw new UncheckedIOException(\"Failed to read StreamingOffset from json\", e);\n    }\n\n    return fromJsonNode(node);\n  }\n\n  @Override","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java#L50-L86","documentation":"StreamingOffset.fromJson throws UncheckedIOException wrapping the message when the offset's JSON string cannot be parsed into a JsonNode (malformed JSON, I/O error from Jackson). It converts the checked IOException into an unchecked one so it can surface from Spark checkpoint deserialization.","triggerScenarios":"Spark structured streaming restores a StreamingOffset from checkpoint state where the stored JSON string is corrupt, truncated, or produced by an incompatible schema/version; calling fromJson directly with a non-JSON string.","commonSituations":"Corrupted or hand-edited checkpoint files; offset JSON written by a different Iceberg version that fails to parse; disk issues truncating checkpoint files during recovery after failure.","solutions":["Inspect and repair the checkpoint location's offset/state JSON files","Delete the corrupted checkpoint and restart the streaming query (data will be reprocessed per source semantics)","Verify all executors/drivers use the same Iceberg version","If calling fromJson manually, validate the string is well-formed JSON before passing it"],"exampleFix":"// before\nStreamingOffset offset = StreamingOffset.fromJson(userProvidedString); // may throw\n// after\ntry {\n  StreamingOffset offset = StreamingOffset.fromJson(json);\n} catch (UncheckedIOException e) {\n  // fall back to re-initializing offsets from the table\n}","handlingStrategy":"try-catch","validationCode":"try { JsonUtil.mapper().readTree(offsetJson); } catch (Exception e) { /* reject/re-initialize before passing to fromJson */ }","typeGuard":null,"tryCatchPattern":"try {\n  StreamingOffset offset = StreamingOffset.fromJson(json);\n} catch (UncheckedIOException e) {\n  // treat as corrupt checkpoint: re-initialize offsets from table state\n}","preventionTips":["Never hand-edit Spark checkpoint files","Keep the same Iceberg version on all nodes of a streaming job","Monitor checkpoint directory for truncation/corruption; re-create checkpoints after version upgrades"],"tags":["spark","streaming","json","checkpoint","deserialization"],"backgroundTag":"json-parse-error","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}