apache/beam · error · UnsupportedOperationException

getCoder is called before init

Error message

getCoder is called before init

What it means

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.

Solutions

  1. Call init(...) on the row mapper before invoking getCoder()
  2. Ensure you are using SingleStoreIO's standard pipeline construction so the source initializes the mapper automatically
  3. In tests, set the schema field (or call the init path with a valid statement/connection) before asserting on getCoder()
  4. Upgrade Beam SingleStore IO if a released version fails to init the mapper before coder resolution (lifecycle bug)

Example fix

// before
SingleStoreDefaultRowMapper mapper = new SingleStoreDefaultRowMapper();
SchemaCoder<Row> coder = mapper.getCoder(); // throws
// after
SingleStoreDefaultRowMapper mapper = new SingleStoreDefaultRowMapper();
mapper.init(statement); // populate schema from ResultSetMetaData
SchemaCoder<Row> coder = mapper.getCoder();
Defensive patterns

Strategy: try-catch

Validate before calling

if (mapperHasSchema(mapper)) { coder = mapper.getCoder(); }

Type guard

boolean mapperInitialized(SingleStoreDefaultRowMapper m) { try { return m.getCoder() != null; } catch (UnsupportedOperationException e) { return false; } }

Try / catch

try { SchemaCoder<Row> coder = mapper.getCoder(); } catch (UnsupportedOperationException e) { throw new IllegalStateException("Row mapper not initialized: call init() before getCoder()", e); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/c6a07cbf95b6a916. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/singlestore/src/main/java/org/apache/beam/sdk/io/singlestore/SingleStoreDefaultRowMapper.java:113

    int fieldCount = schema.getFieldCount();
    for (int i = 0; i < fieldCount; i++) {
      Object value = converters.get(i).getValue(resultSet, i + 1);

      if (resultSet.wasNull() || value == null) {
        rowBuilder.addValue(null);
      } else {
        rowBuilder.addValue(value);
      }
    }

    return rowBuilder.build();
  }

  @Override
  public SchemaCoder<Row> getCoder() throws Exception {
    if (schema == null) {
      throw new UnsupportedOperationException("getCoder is called before init");
    }

    return RowCoder.of(this.schema);
  }

  abstract static class ResultSetFieldConverter implements Serializable {
    abstract @Nullable Object getValue(ResultSet rs, Integer index) throws SQLException;

    Schema.Field getSchemaField(ResultSetMetaData md, Integer index) throws SQLException {
      String label = md.getColumnLabel(index);
      return Schema.Field.of(label, getSchemaFieldType(md, index))
          .withNullable(md.isNullable(index) == java.sql.ResultSetMetaData.columnNullable);
    }

    abstract Schema.FieldType getSchemaFieldType(ResultSetMetaData md, Integer index)
        throws SQLException;

    /**

View on GitHub (pinned to 12126d8942)