xpipe-io/xpipe · error · ValidationException

Value must be an instance of ${classNames}

Error message

Value must be an instance of ${classNames}

What it means

Validators.isAnyType(ref, cs...) validates that a store reference's store is an instance of at least one of the given classes. It throws a ValidationException listing the allowed class simple names when the ref is null, the store is null, or none of the classes match. It is the multi-type variant of isType.

Source

Thrown at app/src/main/java/io/xpipe/app/util/Validators.java:27

public class Validators {

    public static <T extends DataStore> void isType(DataStoreEntryRef<? extends T> ref, Class<T> c)
            throws ValidationException {
        if (ref == null
                || ref.getStore() == null
                || !c.isAssignableFrom(ref.getStore().getClass())) {
            throw new ValidationException("Value must be an instance of " + c.getSimpleName());
        }
    }

    public static <T extends DataStore> void isAnyType(DataStoreEntryRef<? extends T> ref, Class<?>... cs)
            throws ValidationException {
        if (ref == null
                || ref.getStore() == null
                || Arrays.stream(cs)
                        .noneMatch(c -> c.isAssignableFrom(ref.getStore().getClass()))) {
            throw new ValidationException("Value must be an instance of "
                    + Arrays.stream(cs).map(Class::getSimpleName).toList());
        }
    }

    public static void nonNull(Object object) throws ValidationException {
        if (object == null) {
            throw new ValidationException(AppI18n.get("valueMustNotBeEmpty"));
        }
    }

    public static void nonNull(Object object, String name) throws ValidationException {
        if (object == null) {
            throw new ValidationException(AppI18n.get("mustNotBeEmpty", name));
        }
    }

    public static void contentNonNull(List<?> object) throws ValidationException {
        if (object.stream().anyMatch(o -> o == null)) {

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Constrain the store selection UI to the allowed types so only matching entries can be chosen.
  2. Add the intended store class to the varargs list if it is a legitimate new allowed type.
  3. Guard before validating: if (ref != null && ref.getStore() != null && Arrays.stream(cs).anyMatch(c -> c.isInstance(ref.getStore()))) proceed.

Example fix

// before
Validators.isAnyType(ref, HostStore.class, ScriptStore.class);
// after
if (ref != null && ref.getStore() != null) {
    Validators.isAnyType(ref, HostStore.class, ScriptStore.class);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (ref == null || ref.getStore() == null
        || Arrays.stream(cs).noneMatch(c -> c.isInstance(ref.getStore()))) {
    // handle before validation
}

Type guard

public static boolean isAnyStoreType(DataStoreEntryRef<?> ref, Class<?>... cs) {
    return ref != null && ref.getStore() != null
        && Arrays.stream(cs).anyMatch(c -> c.isInstance(ref.getStore()));
}

Try / catch

try {
    Validators.isAnyType(ref, AStore.class, BStore.class);
} catch (ValidationException e) {
    // store matches none of the allowed types
}

Prevention

When it happens

Trigger: Validators.isAnyType(ref, A.class, B.class) where ref is null, the store is null, or the store's class matches neither A nor B; the message shows the Java list of allowed class names.

Common situations: A configuration field accepts several store kinds but the user picked a different one; a new store type was added but not included in the accepted class list; dangling reference after store deletion.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/af51ac5eb08e28e5. Report an issue: GitHub.