{"record":{"id":"36da91f39d20dd4a","repo":"apache/seatunnel","slug":"data-type-cast-failed","errorCode":"DATA_TYPE_CAST_FAILED","errorMessage":"error field:","messagePattern":"error field:","errorType":"error_code","errorClass":"JdbcConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/converter/AbstractJdbcRowConverter.java","lineNumber":228,"sourceCode":"                int statementIndex = fieldIndex + 1;\n                String sourceType = null;\n                if (databaseTableSchema != null && databaseTableSchema.contains(fieldName)) {\n                    sourceType = databaseTableSchema.getColumn(fieldName).getSourceType();\n                }\n                Object fieldValue = row.getField(fieldIndex);\n                if (fieldValue == null) {\n                    setNullToStatementByDataType(\n                            statement, seaTunnelDataType, statementIndex, sourceType);\n                    continue;\n                }\n                setValueToStatementByDataType(\n                        row.getField(fieldIndex),\n                        statement,\n                        seaTunnelDataType,\n                        statementIndex,\n                        sourceType);\n            } catch (Exception e) {\n                throw new JdbcConnectorException(\n                        JdbcConnectorErrorCode.DATA_TYPE_CAST_FAILED,\n                        \"error field:\" + rowType.getFieldNames()[fieldIndex],\n                        e);\n            }\n        }\n        return statement;\n    }\n    /**\n     * Bind a null value to the PreparedStatement parameter.\n     *\n     * <p>Default implementation uses {@link PreparedStatement#setObject(int, Object)}, which works\n     * for most databases. However, some databases (e.g., SQL Server) require explicit type\n     * information for null values in certain column types (e.g., IMAGE, BLOB).\n     *\n     * <p>Subclasses can override this method to provide database-specific null handling. For\n     * example, SQL Server uses {@link PreparedStatement#setNull(int, int)} with the appropriate\n     * JDBC type (e.g., {@link java.sql.Types#LONGVARBINARY} for IMAGE columns).\n     *","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/converter/AbstractJdbcRowConverter.java#L210-L246","documentation":"AbstractJdbcRowConverter.toExternal converts a SeaTunnelRow field into a JDBC statement parameter; if the per-field conversion throws for any field, the exception is wrapped in JdbcConnectorException(DATA_TYPE_CAST_FAILED) with the offending field name. It signals that a value in your data cannot be represented as the target SQL type for that column (conversion code threw inside the converter).","triggerScenarios":"During toExternal(row, statement) — typically in the JDBC sink write path — a row field's value is incompatible with the mapped target type: e.g. null in a primitive-required column, a string too long / unparseable into a numeric or date type, oversized BigDecimal precision, or a bytes/object mismatch.","commonSituations":"Source data contains dirty values (empty strings, out-of-range numbers) destined for strict SQL columns; SeaTunnel schema declared as INT but source yields longs/strings; timezone or date-format parse failures; BigDecimal scale exceeding column scale.","solutions":["Read the message field name and the wrapped cause to identify the offending value and target type","Align the SeaTunnel source schema with the actual data (correct data types, sizes) before the sink","Pre-clean/transform the data (e.g. via a Transform) to null-out or coerce invalid values","Adjust the target column type or converter dialect mapping if the mapping itself is wrong"],"exampleFix":"// before\nschema: { field { name = \"age\" type = INT } }   // source yields \"abc\" strings\n// after\nTransform: filter or Cast age to INT with default, or declare age as STRING and cast in sink target column VARCHAR","handlingStrategy":"try-catch","validationCode":"Object v = row.getField(idx);\nSeaTunnelDataType t = rowType.getFieldType(idx);\nif (v == null && !t nullable-allowed) validate per column config;\nif (v instanceof String s && t == INT_TYPE && !s.matches(\"-?\\\\d+\")) fail fast with field name;","typeGuard":null,"tryCatchPattern":"try {\n    converter.toExternal(row, statement);\n} catch (JdbcConnectorException e) {\n    if (e.getErrorCode() == JdbcConnectorErrorCode.DATA_TYPE_CAST_FAILED) {\n        LOG.error(\"Unconvertible value at field '{}' (row={}); fix schema or clean data\", e.getMessage(), row, e.getCause());\n    }\n    throw e;\n}","preventionTips":["Validate source data types against the declared SeaTunnel schema at read time","Add a data-quality Transform step to null/defaults dirty values before the JDBC sink","Keep BigDecimal scale/precision within the target column limits","Run a small sample batch through the sink before full production runs"],"tags":["jdbc","type-conversion","data-quality","sink"],"backgroundTag":"type-mismatch","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}