{"record":{"id":"a2ec5f20280ba48b","repo":"apache/beam","slug":"failed-to-print-type-row","errorCode":null,"errorMessage":"Failed to print type: {row}","messagePattern":"Failed to print type: (.+?)","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":699,"sourceCode":"    try {\n      final String type =\n          this.printer.print(\n              Optional.ofNullable(valueMap.get(TYPE_COLUMN))\n                  .orElseThrow(IllegalArgumentException::new));\n      return new ColumnType(\n          Optional.ofNullable(valueMap.get(NAME_COLUMN))\n              .orElseThrow(IllegalArgumentException::new)\n              .getStringValue(),\n          new TypeCode(type),\n          Optional.ofNullable(valueMap.get(IS_PRIMARY_KEY_COLUMN))\n              .orElseThrow(IllegalArgumentException::new)\n              .getBoolValue(),\n          (long)\n              Optional.ofNullable(valueMap.get(ORDINAL_POSITION_COLUMN))\n                  .orElseThrow(IllegalArgumentException::new)\n                  .getNumberValue());\n    } catch (InvalidProtocolBufferException exc) {\n      throw new IllegalArgumentException(\"Failed to print type: \" + row);\n    }\n  }\n\n  private Mod modFrom(Struct struct) {\n    final String keys = struct.getJson(KEYS_COLUMN);\n    final String oldValues =\n        struct.isNull(OLD_VALUES_COLUMN) ? null : struct.getJson(OLD_VALUES_COLUMN);\n    final String newValues =\n        struct.isNull(NEW_VALUES_COLUMN) ? null : struct.getJson(NEW_VALUES_COLUMN);\n    return new Mod(keys, oldValues, newValues);\n  }\n\n  private Mod modJsonFrom(Value row) {\n    try {\n      Map<String, Value> valueMap = row.getStructValue().getFieldsMap();\n      final String keys =\n          this.printer.print(\n              Optional.ofNullable(valueMap.get(KEYS_COLUMN))","sourceCodeStart":681,"sourceCodeEnd":717,"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#L681-L717","documentation":"columnTypeJsonFrom converts a JSON row describing a Spanner column type into a ColumnType proto, using a proto printer on extracted fields. If printer.apt/ printing throws InvalidProtocolBufferException, the row's JSON values are malformed for the expected proto-JSON schema and the mapper throws 'Failed to print type'. This signals that the row does not match the expected change stream column-type structure.","triggerScenarios":"Calling columnTypeJsonFrom with a row whose TYPE/ORDINAL_POSITION etc. fields are not valid proto-JSON Value messages, so the protobuf printer throws while serializing; also triggered when required keys resolve to Value objects incompatible with the printer.","commonSituations":"Malformed or hand-crafted test fixtures; rows produced by a different Spanner schema/connector version; corrupted metadata rows; passing wrong Value maps (e.g. missing or wrongly-typed fields) into the mapper.","solutions":["Verify the row contains the expected columns (TYPE, ORDINAL_POSITION, etc.) as valid proto-JSON.","Check that values were parsed with this.parser before being passed to the printer — do not pass raw strings.","Align SDK version: regenerate/refresh rows with the same Beam version that will read them.","Wrap the mapping call in try-catch to surface the offending row without killing the pipeline.","Inspect the row content in the exception message for missing/invalid fields."],"exampleFix":"// before\nColumnType type = mapper.columnTypeJsonFrom(row); // throws on malformed row\n\n// after\ntry {\n  ColumnType type = mapper.columnTypeJsonFrom(row);\n} catch (IllegalArgumentException e) {\n  LOG.error(\"Skipping malformed column-type row: %s\", e.getMessage());\n}","handlingStrategy":"try-catch","validationCode":"boolean hasRequiredColumnTypeFields(java.util.Map<String, com.google.protobuf.Value> map) {\n  return map != null && map.containsKey(\"TYPE\") && map.containsKey(\"ORDINAL_POSITION\");\n}","typeGuard":"boolean isNonNullJsonTypeValue(com.google.protobuf.Value v) {\n  return v != null && v.getKindCase() == com.google.protobuf.Value.KindCase.STRING_VALUE;\n}","tryCatchPattern":"try {\n  ColumnType t = columnTypeJsonFrom(row);\n} catch (IllegalArgumentException e) {\n  LOG.error(\"Cannot map column type row: %s\", e.getMessage());\n}","preventionTips":["Parse rows with the same JsonFormat parser used by the mapper before mapping.","Keep test fixtures generated from real Spanner responses, not hand-written JSON.","Check for required keys (TYPE, ORDINAL_POSITION) before conversion.","Pin connector/SDK versions in CI to avoid format drift."],"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"}