LSPosed/LSPosed · error · ClassNotFoundError

parameter type must either be specified as Class or String

Error message

parameter type must either be specified as Class or String

What it means

In XposedHelpers.getParameterClasses, every non-null vararg element that is not the trailing XC_MethodHook must be either a java.lang.Class or a String class name (resolved via findClass with the given classLoader). Anything else — an Integer for primitive arity hacks, a TypeToken, a lambda, a Parameter object — throws ClassNotFoundError('parameter type must either be specified as Class or String'). Note the thrown type is ClassNotFoundError (a custom Error), not a standard exception.

Source

Thrown at core/src/main/java/de/robv/android/xposed/XposedHelpers.java:631

        Class<?>[] parameterClasses = null;
        for (int i = parameterTypesAndCallback.length - 1; i >= 0; i--) {
            Object type = parameterTypesAndCallback[i];
            if (type == null)
                throw new ClassNotFoundError("parameter type must not be null", null);

            // ignore trailing callback
            if (type instanceof XC_MethodHook)
                continue;

            if (parameterClasses == null)
                parameterClasses = new Class<?>[i + 1];

            if (type instanceof Class)
                parameterClasses[i] = (Class<?>) type;
            else if (type instanceof String)
                parameterClasses[i] = findClass((String) type, classLoader);
            else
                throw new ClassNotFoundError("parameter type must either be specified as Class or String", null);
        }

        // if there are no arguments for the method
        if (parameterClasses == null)
            parameterClasses = new Class<?>[0];

        return parameterClasses;
    }

    /**
     * Returns an array of the given classes.
     */
    public static Class<?>[] getClassesAsArray(Class<?>... clazzes) {
        return clazzes;
    }

    private static String getParametersString(Class<?>... clazzes) {
        StringBuilder sb = new StringBuilder("(");

View on GitHub (pinned to df74d83eb0)

Solutions

  1. Pass java.lang.Class instances (in Kotlin: String::class.java) or full dotted class-name Strings.
  2. For nested/array types pass the correct Class literal: String[].class, or "java.lang.String[]" as a String.
  3. Keep only parameter types plus one trailing XC_MethodHook in the varargs.
  4. If you have arbitrary type tokens, convert them to Class yourself before calling.

Example fix

// before (Kotlin KClass instead of java.lang.Class)
XposedHelpers.findAndHookMethod(clazz, "bind", String::class, callback)

// after
XposedHelpers.findAndHookMethod(clazz, "bind", String::class.java, callback)
Defensive patterns

Strategy: validation

Validate before calling

for (Object o : parameterTypesAndCallback)
    if (o != null && !(o instanceof XC_MethodHook)
            && !(o instanceof Class) && !(o instanceof String))
        throw new IllegalStateException("bad parameter type token: " + o);

Type guard

static boolean isValidTypeToken(Object o) {
    return o instanceof Class || o instanceof String;
}

Try / catch

try {
    XposedHelpers.findAndHookMethod(clazz, name, spec);
} catch (XposedHelpers.ClassNotFoundError e) {
    // spec contained a non-Class/String token; rewrite as Class or String
}

Prevention

When it happens

Trigger: Calling findAndHookMethod(clazz, "m", 3, callback) (Integer as type), or passing kotlin.reflect.KClass instead of java.lang.Class, a java.lang.reflect.Type, a MethodParameter, or an uninitialized object.

Common situations: Kotlin developers passing String::class (KClass) instead of String::class.java; passing Class.forName-adjacent objects like ParameterizedType for generic parameters; porting code from Mockito/other DSLs that accept other type tokens; passing 'null' object boxes or primitives.

Related errors


AI-assisted analysis of LSPosed/LSPosed@df74d83eb0 (2026-08-14). Data as JSON: /api/errors/86cddd9561f899d7. Report an issue: GitHub.