{"record":{"id":"1809a3cc21601640","repo":"apache/iceberg","slug":"failed-to-parse-streamingoffset-from-json-string","errorCode":null,"errorMessage":"Failed to parse StreamingOffset from JSON string ${json}","messagePattern":"Failed to parse StreamingOffset from JSON string (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/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/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java#L50-L86","documentation":"StreamingOffset.fromJson(String) deserializes a Spark Structured Streaming offset from JSON. If Jackson cannot parse the string, the IOException is wrapped in UncheckedIOException with the offending JSON in the message, preserving the cause.","triggerScenarios":"Passing a malformed or truncated JSON string to StreamingOffset.fromJson(String) — e.g. a corrupted offset in the streaming checkpoint's offsets/ directory, or hand-edited offset JSON.","commonSituations":"Corrupted or partially-written checkpoint offset files after a crash; manually editing offsets; reading offsets produced by a different Iceberg version with a changed schema.","solutions":["Inspect and repair the offending JSON in the checkpoint offsets file (message includes the raw string).","Reset/rebuild the streaming checkpoint if the offset is unrecoverable (restart from an earlier checkpoint or trigger once).","Verify the offset JSON matches the expected shape {version, snapshot-id, position, scan-all-files}."],"exampleFix":"// before\nStreamingOffset offset = StreamingOffset.fromJson(\"{snapshot-id: 1,\"); // malformed\n\n// after\nString json = Files.readString(offsetPath);\nPreconditions.checkArgument(json.trim().startsWith(\"{\"), \"Not JSON: %s\", json);\nStreamingOffset offset = StreamingOffset.fromJson(json);","handlingStrategy":"try-catch","validationCode":"String json = readOffsetFile(path);\nif (json == null || !json.trim().startsWith(\"{\")) {\n  throw new IllegalStateException(\"Corrupt StreamingOffset JSON at \" + path);\n}","typeGuard":null,"tryCatchPattern":"try {\n  StreamingOffset offset = StreamingOffset.fromJson(json);\n} catch (UncheckedIOException e) {\n  // recover from an earlier checkpoint offset or reset the checkpoint\n}","preventionTips":["Never hand-edit checkpoint offset files.","Back up the streaming checkpoint directory.","Keep the Iceberg version stable across query restarts."],"tags":["spark","structured-streaming","json","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"}