apache/seatunnel · error · QdrantConnectorException

COMMON-07

COMMON-07

Error message

Unexpected value type for point ID: <sqlType>

What it means

Qdrant point IDs can only be an unsigned integer or a UUID string. QdrantBatchWriter.pointId maps the SeaTunnel SQL type of the id column: INT is parsed as an integer ID and STRING as a UUID; any other SQL type (DOUBLE, BOOLEAN, DATE, etc.) throws QdrantConnectorException with CommonErrorCode.UNSUPPORTED_DATA_TYPE. Called by buildPoint when constructing each document.

Solutions

  1. Cast or remap the id column to INT or STRING in an upstream transform before the Qdrant sink
  2. If ids are large integers, convert them to STRING and use UUID-format values (or a hash) since Qdrant requires u64 or UUID
  3. Fix the declared schema so the id field is typed as int or string
  4. Add a validation/pre-transform step rejecting rows whose id is not convertible to int or UUID

Example fix

// before
// schema declares id as BIGINT -> pointId throws UNSUPPORTED_DATA_TYPE
// after
// transform id to STRING (UUID) before the sink, e.g. in SQL/transform:
// CAST(id AS STRING)  -- or generate UUID.fromString(hash) in a custom transform
Defensive patterns

Strategy: validation

Validate before calling

// check id column type before sink
SqlType idType = idFieldType.getSqlType();
if (idType != SqlType.INT && idType != SqlType.STRING) {
    throw new IllegalArgumentException(
        "Qdrant point id must be INT or STRING, got: " + idType);
}
if (idType == SqlType.STRING) {
    UUID.fromString(idValue.toString()); // must be a valid UUID
}

Type guard

boolean isValidQdrantIdType(SeaTunnelDataType<?> t) {
    return t.getSqlType() == SqlType.INT || t.getSqlType() == SqlType.STRING;
}

Try / catch

try {
    sink.write(row);
} catch (QdrantConnectorException e) {
    if (e.getErrorCode() == CommonErrorCode.UNSUPPORTED_DATA_TYPE
            && e.getMessage().startsWith("Unexpected value type for point ID")) {
        // fix schema/transform id column to INT or UUID STRING
    }
    throw e;
}

Prevention

When it happens

Trigger: The connector's id field is configured with a SQL type other than INT or STRING (e.g. BIGINT, DOUBLE, BOOLEAN), so the switch default fires in pointId during buildPoint.

Common situations: Source data has a numeric id stored as BIGINT/LONG or DECIMAL instead of INT; id column is a date/timestamp; schema mismatch between the configured schema and actual id values.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/c4dfad9ca1f6032b. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-qdrant/src/main/java/org/apache/seatunnel/connectors/seatunnel/qdrant/sink/QdrantBatchWriter.java:150

                            Points.UpsertPoints.newBuilder()
                                    .setCollectionName(collectionName)
                                    .addAllPoints(qdrantDataCache)
                                    .build())
                    .get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("Upsert failed", e);
        }
    }

    public static Points.PointId pointId(SeaTunnelDataType<?> fieldType, Object value) {
        SqlType sqlType = fieldType.getSqlType();
        switch (sqlType) {
            case INT:
                return id(Integer.parseInt(value.toString()));
            case STRING:
                return id(UUID.fromString(value.toString()));
            default:
                throw new QdrantConnectorException(
                        CommonErrorCode.UNSUPPORTED_DATA_TYPE,
                        "Unexpected value type for point ID: " + sqlType.name());
        }
    }

    public static JsonWithInt.Value buildPayload(SeaTunnelDataType<?> fieldType, Object value) {
        SqlType sqlType = fieldType.getSqlType();
        switch (sqlType) {
            case SMALLINT:
            case INT:
            case BIGINT:
                return ValueFactory.value(Integer.parseInt(value.toString()));
            case FLOAT:
            case DOUBLE:
                return ValueFactory.value(Long.parseLong(value.toString()));
            case STRING:
            case DATE:
                return ValueFactory.value(value.toString());

View on GitHub (pinned to cf67b549a7)