{"record":{"id":"e6febc6d5cc944c9","repo":"apache/seatunnel","slug":"commonerrorcodedeprecated-illegal-argument-e6febc","errorCode":"CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT","errorMessage":"Illegal SeaTunnelRowType: {rowRecord}","messagePattern":"Illegal SeaTunnelRowType: (.+?)","errorType":"error_code","errorClass":"IotdbConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-iotdb/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdb/serialize/DefaultSeaTunnelRowDeserializer.java","lineNumber":49,"sourceCode":"import java.time.ZoneOffset;\nimport java.util.Date;\nimport java.util.List;\n\n@AllArgsConstructor\npublic class DefaultSeaTunnelRowDeserializer implements SeaTunnelRowDeserializer {\n\n    private final SeaTunnelRowType rowType;\n\n    @Override\n    public SeaTunnelRow deserialize(RowRecord rowRecord) {\n        return convert(rowRecord);\n    }\n\n    private SeaTunnelRow convert(RowRecord rowRecord) {\n        long timestamp = rowRecord.getTimestamp();\n        List<Field> fields = rowRecord.getFields();\n        if (fields.size() != (rowType.getTotalFields() - 1)) {\n            throw new IotdbConnectorException(\n                    CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT,\n                    \"Illegal SeaTunnelRowType: \" + rowRecord);\n        }\n\n        Object[] seaTunnelFields = new Object[rowType.getTotalFields()];\n        seaTunnelFields[0] = convertTimestamp(timestamp, rowType.getFieldType(0));\n        for (int i = 1; i < rowType.getTotalFields(); i++) {\n            Field field = fields.get(i - 1);\n            if (field == null || field.getDataType() == null) {\n                seaTunnelFields[i] = null;\n                continue;\n            }\n            SeaTunnelDataType<?> seaTunnelFieldType = rowType.getFieldType(i);\n            seaTunnelFields[i] = convert(seaTunnelFieldType, field);\n        }\n        return new SeaTunnelRow(seaTunnelFields);\n    }\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-iotdb/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdb/serialize/DefaultSeaTunnelRowDeserializer.java#L31-L67","documentation":"DefaultSeaTunnelRowDeserializer.convert() builds a SeaTunnelRow from an IoTDB RowRecord and expects the row type to have exactly one more column (the timestamp) than the number of fields in the IoTDB record. When fields.size() != rowType.getTotalFields() - 1, the schema configured for the source does not match the data IoTDB returns, so it throws ILLEGAL_ARGUMENT.","triggerScenarios":"Calling convert(RowRecord) where the number of measurement fields in the IoTDB RowRecord does not equal rowType.getTotalFields() minus 1 — i.e. the configured SeaTunnelRowType (from the query/schema) diverges from the actual IoTDB timeseries fields.","commonSituations":"IoTDB schema evolved (measurements added/removed or a wildcard query like select ** from ...) after the catalog/table schema was resolved; alignment on the wrong device; query pattern mismatch with configured field list; catalog plugin resolved stale metadata.","solutions":["Re-read the table so the SeaTunnelRowType is resolved against the current IoTDB schema; avoid wildcard queries whose result columns can drift","Compare the configured column list with 'SHOW DEVICES' / 'SHOW TIMESERIES' output and align them exactly (timestamp column + N measurements)","Pin the query to an explicit field list instead of ** so schema drift cannot change the field count","Upgrade the connector/catalog if IoTDB metadata changes are frequent; re-run job after schema changes"],"exampleFix":"// before (wildcard query that drifts)\nquery = \"select ** from root.db.device1\"\n// after (explicit fields matching configured rowType)\nquery = \"select s_temperature, s_humidity from root.db.device1\"","handlingStrategy":"validation","validationCode":"// before running the job, compare field counts\n// SeaTunnelRowType rowType; RowRecord rec;\nif (rec.getFields().size() != rowType.getTotalFields() - 1) {\n    throw new IllegalStateException(\"Schema drift: IoTDB returned \" + rec.getFields().size()\n        + \" fields, schema expects \" + (rowType.getTotalFields() - 1));\n}","typeGuard":"boolean schemaMatches(RowRecord rec, SeaTunnelRowType rowType) {\n    return rec.getFields().size() == rowType.getTotalFields() - 1;\n}","tryCatchPattern":"try {\n    SeaTunnelRow row = deserializer.deserialize(record);\n} catch (IotdbConnectorException e) {\n    if (e.getCode() == CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT) {\n        // re-resolve catalog schema and restart\n    } else { throw e; }\n}","preventionTips":["Use explicit measurement lists in queries instead of wildcards (select **)","Re-resolve the catalog schema after any IoTDB DDL change","Pin the IoTDB schema version used by long-running jobs"],"tags":["iotdb","schema-mismatch","deserialization"],"backgroundTag":"schema-validation-failed","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"}