apache/flink · error · UnsupportedOperationException

Unsupported variant type: {}

Error message

Unsupported variant type: {}

What it means

VariantSerializer only knows how to serialize the BinaryVariant concrete form (which carries value + metadata bytes). Its toBinaryVariant helper throws UnsupportedOperationException for any other Variant implementation, enforcing the invariant that the serializer receives the binary representation produced by the official builder.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeutils/base/VariantSerializer.java:115

    public void copy(DataInputView source, DataOutputView target) throws IOException {
        int valueLength = source.readInt();
        int metadataLength = source.readInt();
        target.writeInt(valueLength);
        target.writeInt(metadataLength);
        target.write(source, valueLength + metadataLength);
    }

    @Override
    public TypeSerializerSnapshot<Variant> snapshotConfiguration() {
        return new VariantSerializerSnapshot();
    }

    private BinaryVariant toBinaryVariant(Variant variant) {
        if (variant instanceof BinaryVariant) {
            return (BinaryVariant) variant;
        }

        throw new UnsupportedOperationException("Unsupported variant type: " + variant.getClass());
    }

    @Internal
    public static final class VariantSerializerSnapshot
            extends SimpleTypeSerializerSnapshot<Variant> {
        /** Constructor to create snapshot from serializer (writing the snapshot). */
        public VariantSerializerSnapshot() {
            super(() -> INSTANCE);
        }
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Always build Variant values through BinaryVariantBuilder (the public builder), whose build() returns a BinaryVariant that the serializer accepts.
  2. Route Variant data through the SQL/Table API, which converts to BinaryVariant automatically.
  3. If you hold a non-binary Variant, convert it to BinaryVariant before it reaches any serializer-backed sink/state.
  4. Do not implement the Variant interface yourself for data that will be serialized.

Example fix

// before: serializer.serialize(myCustomVariant);  // throws: Unsupported variant type
// after: BinaryVariant bv = BinaryVariantBuilder.ofString("x").build();  // build() returns BinaryVariant
//       serializer.serialize(bv);
Defensive patterns

Strategy: type-guard

Type guard

static boolean isSerializableVariant(Variant v) {
    return v instanceof BinaryVariant;
}

// usage before serialize:
if (!isSerializableVariant(myVariant)) {
    BinaryVariant bv = BinaryVariantBuilder.ofString(myValue).build(); // rebuild as BinaryVariant
    serializer.serialize(bv, target);
} else {
    serializer.serialize(myVariant, target);
}

Try / catch

try {
    serializer.serialize(variant, target);
} catch (UnsupportedOperationException e) {
    if (e.getMessage().contains("Unsupported variant type")) {
        log.error("Variant must be a BinaryVariant; rebuild via BinaryVariantBuilder before serializing");
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a Variant that is not a BinaryVariant to VariantSerializer.serialize/copy — e.g., a custom Variant implementation or a Variant built through a path that did not yield a BinaryVariant.

Common situations: Using the internal Variant API directly instead of the public SQL/Table path; implementing the Variant interface in a custom class and feeding it to a sink or keyed state typed with Variant; bypassing BinaryVariantBuilder.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/a1838b3c2bdd9bf5. Report an issue: GitHub.