{"record":{"id":"e80bebad9fd3adfc","repo":"apache/beam","slug":"failed-to-print-mod-row","errorCode":null,"errorMessage":"Failed to print mod: {row}","messagePattern":"Failed to print mod: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/mapper/ChangeStreamRecordMapper.java","lineNumber":734,"sourceCode":"          this.printer.print(\n              Optional.ofNullable(valueMap.get(KEYS_COLUMN))\n                  .orElseThrow(IllegalArgumentException::new));\n\n      final String oldValues =\n          !valueMap.containsKey(\"old_values\")\n              ? null\n              : this.printer.print(\n                  Optional.ofNullable(valueMap.get(OLD_VALUES_COLUMN))\n                      .orElseThrow(IllegalArgumentException::new));\n      final String newValues =\n          !valueMap.containsKey(\"new_values\")\n              ? null\n              : this.printer.print(\n                  Optional.ofNullable(valueMap.get(NEW_VALUES_COLUMN))\n                      .orElseThrow(IllegalArgumentException::new));\n      return new Mod(keys, oldValues, newValues);\n    } catch (InvalidProtocolBufferException exc) {\n      throw new IllegalArgumentException(\"Failed to print mod: \" + row);\n    }\n  }\n\n  private ModType modTypeFrom(String name) {\n    try {\n      return ModType.valueOf(name);\n    } catch (IllegalArgumentException e) {\n      // This is not logged to prevent flooding users with messages\n      return ModType.UNKNOWN;\n    }\n  }\n\n  private ValueCaptureType valueCaptureTypeFrom(String name) {\n    try {\n      return ValueCaptureType.valueOf(name);\n    } catch (IllegalArgumentException e) {\n      // This is not logged to prevent flooding users with messages\n      return ValueCaptureType.UNKNOWN;","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/mapper/ChangeStreamRecordMapper.java#L716-L752","documentation":"modFrom converts a JSON row's KEYS/OLD_VALUES/NEW_VALUES columns into a Mod object using the protobuf JSON printer. If printing any of these Value maps throws InvalidProtocolBufferException, the mapper throws 'Failed to print mod'. The row does not conform to the expected change stream mod structure.","triggerScenarios":"A row whose KEYS_COLUMN, OLD_VALUES_COLUMN, or NEW_VALUES_COLUMN contains Values that fail protobuf JSON printing, or a NEW_VALUES/OLD_VALUES entry missing (orElseThrow(IllegalArgumentException::new)) combined with a printer failure — surfaced from the modFrom path exercised by the ChangeStreamRecordMapper constructor's public flow.","commonSituations":"Hand-written unit-test fixtures with invalid mod JSON; rows written by a mismatched connector version; nullability mismatches between what the caller passes and what modFrom expects; corrupted Spanner metadata rows.","solutions":["Ensure KEYS/OLD_VALUES/NEW_VALUES entries are valid proto-JSON Values parsed with this.parser before mapping.","Check which of oldValues/newValues is null vs missing — provide the expected Value map or adjust nullability handling.","Confirm the row format matches the Beam version's ChangeStreamRecordMapper expectations.","Add try-catch around mod extraction to log and skip bad rows.","Inspect the printed row in the message to identify the failing column."],"exampleFix":"// before\nMod mod = mapper.modFrom(struct); // throws 'Failed to print mod'\n\n// after\nString keysJson = struct.getJson(\"Keys\");\nif (keysJson == null || !keysJson.trim().startsWith(\"{\")) {\n  throw new IllegalArgumentException(\"Invalid mod keys JSON: \" + keysJson);\n}\nMod mod = mapper.modFrom(struct);","handlingStrategy":"validation","validationCode":"boolean isPrintableMod(Struct struct) {\n  String keys = struct.getJson(\"Keys\");\n  return keys != null && keys.trim().startsWith(\"{\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  Mod mod = modFrom(struct);\n} catch (IllegalArgumentException e) {\n  LOG.error(\"Failed to map mod for row: %s\", e.getMessage());\n}","preventionTips":["Verify KEYS/OLD_VALUES/NEW_VALUES columns exist and are valid proto-JSON.","Decide nullability policy explicitly: null Value vs missing key.","Generate test mod fixtures from real change stream output.","Log the offending row for offline inspection when this fires."],"tags":["java","spanner","protobuf","serialization","data-mapping"],"backgroundTag":"json-marshal-failed","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"}