{"record":{"id":"f51bc8eb554b692b","repo":"apache/beam","slug":"unable-to-create-prepared-statement-for-type-type","errorCode":null,"errorMessage":"Unable to create prepared statement for type: ${type}","messagePattern":"Unable to create prepared statement for type: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/jdbc/src/main/java/org/apache/beam/sdk/io/jdbc/JdbcUtil.java","lineNumber":382,"sourceCode":"      throws SQLException {\n    ps.setNull(i + 1, type.getVendorTypeNumber());\n  }\n\n  static class BeamRowPreparedStatementSetter implements JdbcIO.PreparedStatementSetter<Row> {\n    @Override\n    public void setParameters(Row row, PreparedStatement statement) {\n      Schema schema = row.getSchema();\n      List<Schema.Field> fieldTypes = schema.getFields();\n      IntStream.range(0, fieldTypes.size())\n          .forEachOrdered(\n              i -> {\n                Schema.FieldType type = fieldTypes.get(i).getType();\n                try {\n                  JdbcUtil.getPreparedStatementSetCaller(type)\n                      .set(row, statement, i, SchemaUtil.FieldWithIndex.of(schema.getField(i), i));\n                } catch (SQLException throwables) {\n                  throwables.printStackTrace();\n                  throw new RuntimeException(\n                      String.format(\"Unable to create prepared statement for type: %s\", type),\n                      throwables);\n                }\n              });\n    }\n  }\n\n  private static JdbcIO.PreparedStatementSetCaller createBytesCaller() {\n    return (element, ps, i, fieldWithIndex) -> {\n      byte[] value = element.getBytes(fieldWithIndex.getIndex());\n      if (value != null) {\n        validateLogicalTypeLength(fieldWithIndex.getField(), value.length);\n      }\n      ps.setBytes(i + 1, value);\n    };\n  }\n\n  private static JdbcIO.PreparedStatementSetCaller createStringCaller() {","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/jdbc/src/main/java/org/apache/beam/sdk/io/jdbc/JdbcUtil.java#L364-L400","documentation":"Thrown by JdbcIo's statement parameter setter when a JDBC PreparedStatement setXxx call fails with a SQLException while binding a Beam schema row field to the SQL statement. The Beam FieldType is mapped to a typed caller via JdbcUtil.getPreparedStatementSetCaller(type); if the driver rejects the value for that column/type, this wrapper is raised with the offending type in the message.","triggerScenarios":"Writing a Beam row to JDBC where row field i has a type whose value cannot be bound by the driver: e.g. a string longer than the column (CHAR/VARCHAR overflow), a NaN/infinite DOUBLE on drivers that reject it, or a logical-type value incompatible with the mapped setXxx call.","commonSituations":"Schema drift between Beam pipeline output and database table (column narrowed after pipeline was built); inserting oversized VARCHAR/DECIMAL values; PostgreSQL rejecting infinite/NaN doubles; inserting into a column with a mismatched precision.","solutions":["Compare the row's schema field types with the actual database table column definitions and widen/align the column (ALTER TABLE) or truncate/coerce the value in the pipeline","Catch SQLException details in the chained cause (getCause()) to identify which field/value failed","For string fields, pre-validate lengths in a DoFn before JdbcIo.write()","Ensure the JDBC driver version matches the database server version to avoid binding quirks"],"exampleFix":"// before\nrows.apply(JdbcIO.<Row>write().withDataSourceConfiguration(cfg).withStatement(INSERT));\n// after: truncate oversized strings first\nrows.apply(ParDo.of(new DoFn<Row, Row>() {\n  @ProcessElement public void process(ProcessContext c) {\n    Row r = c.element();\n    String v = r.getString(0);\n    c.element(Row.fromRow(r).withValue(0, v != null && v.length() > 255 ? v.substring(0, 255) : v).build());\n  }\n})).apply(JdbcIO.<Row>write()...);","handlingStrategy":"validation","validationCode":"for (int i = 0; i < row.getSchema().getFieldCount(); i++) {\n  Schema.FieldType t = row.getSchema().getField(i).getType();\n  Object v = row.getValue(i);\n  if (v instanceof String && t.equals(Schema.FieldType.STRING)) {\n    // check against known column capacity\n    if (((String) v).length() > 255) throw new IllegalArgumentException(\"field \" + i + \" too long\");\n  }\n  if (v instanceof Double && (Double.isInfinite((Double) v) || Double.isNaN((Double) v))) {\n    throw new IllegalArgumentException(\"field \" + i + \" is NaN/Inf, driver may reject it\");\n  }\n}","typeGuard":"boolean isBindable(Object v) {\n  return v == null || v instanceof String || v instanceof Number || v instanceof Boolean\n      || v instanceof java.sql.Timestamp || v instanceof java.sql.Date;\n}","tryCatchPattern":"try {\n  rows.apply(JdbcIO.<Row>write().withDataSourceConfiguration(cfg).withStatement(sql));\n} catch (RuntimeException e) {\n  if (e.getMessage().startsWith(\"Unable to create prepared statement for type\")) {\n    LOG.error(\"JDBC bind failed for type {}; cause: {}\", e.getCause());\n  }\n  throw e;\n}","preventionTips":["Align Beam schema field types with actual table DDL before writing","Pre-truncate/validate string lengths against column capacities","Avoid NaN/Infinity doubles for drivers that reject them","Keep JDBC driver version in sync with the database server"],"tags":["jdbc","beam","sql","data-binding"],"backgroundTag":"database-write-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"}