{"record":{"id":"c6a07cbf95b6a916","repo":"apache/beam","slug":"getcoder-is-called-before-init","errorCode":null,"errorMessage":"getCoder is called before init","messagePattern":"getCoder is called before init","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/singlestore/src/main/java/org/apache/beam/sdk/io/singlestore/SingleStoreDefaultRowMapper.java","lineNumber":113,"sourceCode":"\n    int fieldCount = schema.getFieldCount();\n    for (int i = 0; i < fieldCount; i++) {\n      Object value = converters.get(i).getValue(resultSet, i + 1);\n\n      if (resultSet.wasNull() || value == null) {\n        rowBuilder.addValue(null);\n      } else {\n        rowBuilder.addValue(value);\n      }\n    }\n\n    return rowBuilder.build();\n  }\n\n  @Override\n  public SchemaCoder<Row> getCoder() throws Exception {\n    if (schema == null) {\n      throw new UnsupportedOperationException(\"getCoder is called before init\");\n    }\n\n    return RowCoder.of(this.schema);\n  }\n\n  abstract static class ResultSetFieldConverter implements Serializable {\n    abstract @Nullable Object getValue(ResultSet rs, Integer index) throws SQLException;\n\n    Schema.Field getSchemaField(ResultSetMetaData md, Integer index) throws SQLException {\n      String label = md.getColumnLabel(index);\n      return Schema.Field.of(label, getSchemaFieldType(md, index))\n          .withNullable(md.isNullable(index) == java.sql.ResultSetMetaData.columnNullable);\n    }\n\n    abstract Schema.FieldType getSchemaFieldType(ResultSetMetaData md, Integer index)\n        throws SQLException;\n\n    /**","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/singlestore/src/main/java/org/apache/beam/sdk/io/singlestore/SingleStoreDefaultRowMapper.java#L95-L131","documentation":"SingleStoreDefaultRowMapper.getCoder() returns a RowCoder built from the schema discovered during init(). If init() has not run yet, schema is null and the mapper refuses to return a coder, throwing UnsupportedOperationException. This is a lifecycle guard: the mapper cannot infer a Beam schema before it connects to the database and reads result-set metadata.","triggerScenarios":"Calling getCoder() on a SingleStoreDefaultRowMapper instance before calling init(). This happens when a SingleStoreIO read is built with a custom row mapper but the mapper is not initialized by the source before coder resolution, or when user code invokes getCoder() directly on a freshly constructed mapper.","commonSituations":"Supplying SingleStoreIO.read().withRowMapper(new MyMapper()) where the mapper relies on default init order and gets queried early; unit tests instantiating the mapper and calling getCoder() without init(); refactoring that moves coder resolution before source initialization.","solutions":["Call init(...) on the row mapper before invoking getCoder()","Ensure you are using SingleStoreIO's standard pipeline construction so the source initializes the mapper automatically","In tests, set the schema field (or call the init path with a valid statement/connection) before asserting on getCoder()","Upgrade Beam SingleStore IO if a released version fails to init the mapper before coder resolution (lifecycle bug)"],"exampleFix":"// before\nSingleStoreDefaultRowMapper mapper = new SingleStoreDefaultRowMapper();\nSchemaCoder<Row> coder = mapper.getCoder(); // throws\n// after\nSingleStoreDefaultRowMapper mapper = new SingleStoreDefaultRowMapper();\nmapper.init(statement); // populate schema from ResultSetMetaData\nSchemaCoder<Row> coder = mapper.getCoder();","handlingStrategy":"try-catch","validationCode":"if (mapperHasSchema(mapper)) { coder = mapper.getCoder(); }","typeGuard":"boolean mapperInitialized(SingleStoreDefaultRowMapper m) { try { return m.getCoder() != null; } catch (UnsupportedOperationException e) { return false; } }","tryCatchPattern":"try { SchemaCoder<Row> coder = mapper.getCoder(); } catch (UnsupportedOperationException e) { throw new IllegalStateException(\"Row mapper not initialized: call init() before getCoder()\", e); }","preventionTips":["Always construct mappers through SingleStoreIO's pipeline API so init() runs automatically","Never call getCoder() directly on a mapper you did not init in the same scope","In tests, use the same init path as production before asserting on coder behavior"],"tags":["java","beam","lifecycle","unsupported-operation"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}