apache/flink · critical · UnsupportedOperationException

This object is a dummy TypeSerializer.

Error message

This object is a dummy TypeSerializer.

What it means

Thrown by UnloadableDummyTypeSerializer.isImmutableType() when the runtime attempts to query mutability on a dummy serializer. An UnloadableDummyTypeSerializer is created when a serializer snapshot cannot restore its real serializer because the serializer class is missing from the classpath (ClassNotFoundException) or has an incompatible serial version (InvalidClassException). The dummy preserves the raw serialized bytes so they are not lost on re-checkpoint, but it cannot perform any real serializer operation. isImmutableType is typically called by the state backend to decide copy-on-read behavior.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeutils/UnloadableDummyTypeSerializer.java:63

    }

    public UnloadableDummyTypeSerializer(byte[] actualBytes, @Nullable Throwable originalError) {
        this.actualBytes = Preconditions.checkNotNull(actualBytes);
        this.originalError = originalError;
    }

    public byte[] getActualBytes() {
        return actualBytes;
    }

    @Nullable
    public Throwable getOriginalError() {
        return originalError;
    }

    @Override
    public boolean isImmutableType() {
        throw new UnsupportedOperationException("This object is a dummy TypeSerializer.");
    }

    @Override
    public TypeSerializer<T> duplicate() {
        throw new UnsupportedOperationException("This object is a dummy TypeSerializer.");
    }

    @Override
    public T createInstance() {
        throw new UnsupportedOperationException("This object is a dummy TypeSerializer.");
    }

    @Override
    public T copy(T from) {
        throw new UnsupportedOperationException("This object is a dummy TypeSerializer.");
    }

    @Override

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Ensure the JAR containing the serializer class and the POJO class is on the classpath at restore time (include it in the job submission).
  2. If the class was moved/renamed, restore from the old class location first, take a savepoint, then migrate.
  3. Maintain serialVersionUID on custom serializers and implement a proper TypeSerializerSnapshot for migration.
  4. If the class is genuinely gone, write a compatible replacement serializer with a snapshot that handles the old format.
Defensive patterns

Strategy: fallback

Validate before calling

// Before restore, verify the serializer/type class is loadable on the classpath
try {
    Class.forName("com.example.MyStateType");
    Class.forName("com.example.MyTypeSerializer");
} catch (ClassNotFoundException e) {
    throw new IllegalStateException(
        "Missing class on classpath — include the user-code JAR before restore", e);
}

Try / catch

try {
    env.execute("job");
} catch (Exception e) {
    if (e.getCause() instanceof UnsupportedOperationException
            && e.getMessage().contains("dummy TypeSerializer")) {
        log.error("Serializer class missing at restore. Add the JAR and restart.");
    }
    throw e;
}

Prevention

When it happens

Trigger: Restoring a checkpoint/savepoint whose state serializer class is not on the job's classpath at restore time. Common when the user JAR with the serializer/POJO class is not submitted, was renamed, moved packages, or its serialVersionUID changed. Any state-backend operation that calls isImmutableType on the dummy then throws.

Common situations: Submitting a job without the user-code JAR that contains the POJO or custom serializer. Refactoring a POJO to a different package between the checkpoint and the restore. Changing a custom serializer's class without maintaining serialVersionUID or a TypeSerializerSnapshot migration path. Upgrading a connector or UDF library whose internal serializer class changed.

Related errors


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