apache/flink · error · UnsupportedOperationException

Tuple0 cannot take any data, as it has zero fields.

Error message

Tuple0 cannot take any data, as it has zero fields.

What it means

Tuple0Serializer is the serializer for the zero-arity Tuple0 type. createInstance(Object[] fields) rejects any attempt to initialize a Tuple0 with field values, because Tuple0 has no fields at all: an empty array (or null) yields Tuple0.INSTANCE, anything else throws UnsupportedOperationException. It signals a programming error where field data was routed to a zero-arity tuple type.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/Tuple0Serializer.java:57

    // ------------------------------------------------------------------------

    @Override
    public Tuple0Serializer duplicate() {
        return this;
    }

    @Override
    public Tuple0 createInstance() {
        return Tuple0.INSTANCE;
    }

    @Override
    public Tuple0 createInstance(Object[] fields) {
        if (fields == null || fields.length == 0) {
            return Tuple0.INSTANCE;
        }

        throw new UnsupportedOperationException(
                "Tuple0 cannot take any data, as it has zero fields.");
    }

    @Override
    public Tuple0 copy(Tuple0 from) {
        return from;
    }

    @Override
    public Tuple0 copy(Tuple0 from, Tuple0 reuse) {
        return reuse;
    }

    @Override
    public int getLength() {
        return 1;
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Guard before calling: if the target serializer is Tuple0Serializer (arity == 0), pass an empty array (or just use Tuple0.INSTANCE) instead of the source fields.
  2. Fix the upstream projection/type so that the tuple arity matches the number of fields being supplied; Tuple0 should only appear when there is genuinely no data.
  3. In generic field-copy code, branch on tuple arity: arity 0 -> Tuple0.INSTANCE, otherwise createInstance(fields).

Example fix

// before
Object[] fields = new Object[] { "leftover" };
Tuple0 t = (Tuple0) tuple0Serializer.createInstance(fields); // throws 686

// after
Object[] fields = new Object[0]; // or: Tuple0 t = Tuple0.INSTANCE;
Tuple0 t = (Tuple0) tuple0Serializer.createInstance(fields);
Defensive patterns

Strategy: type-guard

Validate before calling

Object[] fieldsForTuple0 = (tupleSerializer.getArity() == 0) ? new Object[0] : fields;
Tuple0 t = (Tuple0) tupleSerializer.createInstance(fieldsForTuple0);

Type guard

public static boolean isTuple0Serializer(TupleSerializer<?> s) {
    return s.getArity() == 0;
}

Try / catch

try {
    return ser.createInstance(fields);
} catch (UnsupportedOperationException e) {
    if (ser.getArity() == 0) return (T) Tuple0.INSTANCE; // arity 0 carries no data
    throw e;
}

Prevention

When it happens

Trigger: Calling Tuple0Serializer.createInstance(Object[]) with a non-empty array; e.g. building a projection/operator that feeds N field values into a Tuple-typed output whose TypeInformation resolved to Tuple0 (arity 0), or reflection-based field-copy utilities that pass a source record's fields into a Tuple0 target.

Common situations: Projection that selects zero columns but still passes the original field array downstream. Type erasure/generic misuse where the expected Tuple2 got replaced by Tuple0. Code that uniformly does serializer.createInstance(recordFields) across tuple arities and hits arity 0. Pojo-to-Tuple conversion with an empty field list.

Related errors


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