apache/pulsar · error · IllegalArgumentException

Schema type mismatch ${typeArg} vs ${schemaTypeArg}

Error message

Schema type mismatch ${typeArg} vs ${schemaTypeArg}

What it means

Thrown by ValidatorUtils.validateSchemaType (invoked from validateSchema) when a custom input Schema's declared type argument is not assignable to the function's input type argument. For input schemas, the Schema<T>'s T must be assignable TO the function's input type, guaranteeing decoded records match the function's parameter type.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java:185

            if (!serDeTypeArg.asErasure().isAssignableFrom(typeArg.asErasure())) {
                throw new IllegalArgumentException("Serializer type mismatch " + typeArg.getActualName() + " vs "
                        + serDeTypeArg.getActualName());
            }
        }
    }

    private static void validateSchemaType(TypeDefinition schema, TypeDefinition typeArg, TypePool typePool,
                                           boolean input) {

        TypeDescription.Generic schemaTypeArg = schema.getInterfaces().stream()
                .filter(i -> i.asErasure().isAssignableTo(Schema.class))
                .findFirst()
                .map(i -> i.getTypeArguments().get(0))
                .orElse(null);

        if (input) {
            if (!schemaTypeArg.asErasure().isAssignableTo(typeArg.asErasure())) {
                throw new IllegalArgumentException(
                        "Schema type mismatch " + typeArg.getActualName() + " vs " + schemaTypeArg.getActualName());
            }
        } else {
            if (!schemaTypeArg.asErasure().isAssignableFrom(typeArg.asErasure())) {
                throw new IllegalArgumentException(
                        "Schema type mismatch " + typeArg.getActualName() + " vs " + schemaTypeArg.getActualName());
            }
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Align the function's input type with the schema's type argument (make the function accept the schema's type).
  2. Update the custom Schema class so its Schema<T> type argument is the function's input type (or a subtype of it).
  3. Use a built-in schema type (e.g. JSON, AVRO) keyed to the correct class instead of the mismatched custom schema.

Example fix

// before
public class FooSchema implements Schema<Bar> { ... }
public class MyFunction implements Function<Foo, Void> { ... }
// after
public class FooSchema implements Schema<Foo> { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean inputSchemaMatches(Class<?> schemaClass, Class<?> inputType) {
    for (Type t : schemaClass.getGenericInterfaces()) {
        if (t instanceof ParameterizedType && ((ParameterizedType) t).getRawType() == Schema.class) {
            Type arg = ((ParameterizedType) t).getActualTypeArguments()[0];
            return arg instanceof Class<?> && ((Class<?>) arg).isAssignableFrom(inputType);
        }
    }
    return false;
}

Type guard

static <T> boolean isSchemaFor(Class<? extends Schema<T>> schemaClass, Class<T> type) {
    return Schema.class.isAssignableFrom(schemaClass);
}

Try / catch

try {
    ValidatorUtils.validateSchema(schemaType, typeArg, typePool, true);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Schema type mismatch")) {
        throw new IllegalStateException("Input schema " + schemaType
            + " produces a type incompatible with the function's input parameter", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: validateSchema(schemaType, typeArg, typePool, true) with a custom (non-builtin) schemaType class that implements Schema<T>, where schemaTypeArg.asErasure().isAssignableTo(typeArg.asErasure()) is false — e.g. function input is Foo but the schema is SchemaImpl<Bar>.

Common situations: Custom Schema implementation written for a different POJO than the function consumes; function input type evolved (Avro class regenerated) while schema class was not; mixing a JSON schema of one type with a typed function parameter; configs copied between functions.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/d2fd8338f08a16de. Report an issue: GitHub.