apache/seatunnel · error · IllegalArgumentException

Unknown MetalakeClient type:

Error message

Unknown MetalakeClient type: 

What it means

IllegalArgumentException thrown by MetaLakeFactory.createClient when the given MetaLakeType has no registered constructor in CLIENT_REGISTRY. Since metaLakeType is an enum, this indicates the enum value's lowercase name is not present in the registry (registry/enum mismatch, e.g. after adding a new enum value without registering it).

Source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/metalake/MetaLakeFactory.java:49

    private static final Map<String, Supplier<MetaLakeTableSchemaConvertor>> MAPPER_REGISTRY =
            new HashMap<>();

    static {
        register(MetaLakeType.GRAVITINO.getType());
    }

    private MetaLakeFactory() {}

    public static void register(String type) {
        CLIENT_REGISTRY.put(type.toLowerCase(), GravitinoClient::new);
        MAPPER_REGISTRY.put(type.toLowerCase(), GravitinoTableSchemaConvertor::new);
    }

    public static MetalakeClient createClient(MetaLakeType metaLakeType) {
        String type = metaLakeType.name().toLowerCase();
        Supplier<MetalakeClient> constructor = CLIENT_REGISTRY.get(type.toLowerCase());
        if (constructor == null) {
            throw new IllegalArgumentException("Unknown MetalakeClient type: " + type);
        }
        return constructor.get();
    }

    public static MetaLakeTableSchemaConvertor createTypeMapper(MetaLakeType metaLakeType) {
        String type = metaLakeType.name().toLowerCase();
        Supplier<MetaLakeTableSchemaConvertor> constructor =
                MAPPER_REGISTRY.get(type.toLowerCase());
        if (constructor == null) {
            throw new IllegalArgumentException("Unknown MetaLakeTypeMapper type: " + type);
        }
        return constructor.get();
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check CLIENT_REGISTRY in MetaLakeFactory and register a Supplier for the missing type.
  2. Ensure the enum value name (lowercased) exactly matches the registry key string.
  3. Rebuild/redeploy so the MetaLakeFactory version matches the MetaLakeType version on the classpath.
  4. Add a unit test iterating all MetaLakeType values against createClient to catch drift.

Example fix

// before
private static final Map<String, Supplier<MetalakeClient>> CLIENT_REGISTRY =
        Map.of("gravitino", GravitinoClient::new);
// after
private static final Map<String, Supplier<MetalakeClient>> CLIENT_REGISTRY =
        Map.of("gravitino", GravitinoClient::new, "newtype", NewTypeClient::new);
Defensive patterns

Strategy: validation

Validate before calling

// registry-coverage test
test void allTypesHaveClients() {
    for (MetaLakeType t : MetaLakeType.values()) {
        assertNotNull(MetaLakeFactory.createClient(t));
    }
}

Try / catch

try {
    return MetaLakeFactory.createClient(type);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Metalake type " + type + " not registered in CLIENT_REGISTRY; upgrade mismatch?", e);
}

Prevention

When it happens

Trigger: Calling createClient(MetaLakeType.X) where X.name().toLowerCase() is not a key in CLIENT_REGISTRY — typically a newly added MetaLakeType missing its registry entry, or a registry key typo.

Common situations: Upgrading SeaTunnel where a new metalake type was added but the factory registry was not updated; plugin/classpath mismatch loading an older MetaLakeFactory; custom enum values contributed by extensions.

Related errors


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