{"record":{"id":"86cddd9561f899d7","repo":"LSPosed/LSPosed","slug":"parameter-type-must-either-be-specified-as-class-o","errorCode":null,"errorMessage":"parameter type must either be specified as Class or String","messagePattern":"parameter type must either be specified as Class or String","errorType":"exception","errorClass":"ClassNotFoundError","httpStatus":null,"severity":"error","filePath":"core/src/main/java/de/robv/android/xposed/XposedHelpers.java","lineNumber":631,"sourceCode":"        Class<?>[] parameterClasses = null;\n        for (int i = parameterTypesAndCallback.length - 1; i >= 0; i--) {\n            Object type = parameterTypesAndCallback[i];\n            if (type == null)\n                throw new ClassNotFoundError(\"parameter type must not be null\", null);\n\n            // ignore trailing callback\n            if (type instanceof XC_MethodHook)\n                continue;\n\n            if (parameterClasses == null)\n                parameterClasses = new Class<?>[i + 1];\n\n            if (type instanceof Class)\n                parameterClasses[i] = (Class<?>) type;\n            else if (type instanceof String)\n                parameterClasses[i] = findClass((String) type, classLoader);\n            else\n                throw new ClassNotFoundError(\"parameter type must either be specified as Class or String\", null);\n        }\n\n        // if there are no arguments for the method\n        if (parameterClasses == null)\n            parameterClasses = new Class<?>[0];\n\n        return parameterClasses;\n    }\n\n    /**\n     * Returns an array of the given classes.\n     */\n    public static Class<?>[] getClassesAsArray(Class<?>... clazzes) {\n        return clazzes;\n    }\n\n    private static String getParametersString(Class<?>... clazzes) {\n        StringBuilder sb = new StringBuilder(\"(\");","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/LSPosed/LSPosed/blob/df74d83eb03a44cc6ad268841ac2ada28d077c77/core/src/main/java/de/robv/android/xposed/XposedHelpers.java#L613-L649","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass java.lang.Class instances (in Kotlin: String::class.java) or full dotted class-name Strings.","For nested/array types pass the correct Class literal: String[].class, or \"java.lang.String[]\" as a String.","Keep only parameter types plus one trailing XC_MethodHook in the varargs.","If you have arbitrary type tokens, convert them to Class yourself before calling."],"exampleFix":"// before (Kotlin KClass instead of java.lang.Class)\nXposedHelpers.findAndHookMethod(clazz, \"bind\", String::class, callback)\n\n// after\nXposedHelpers.findAndHookMethod(clazz, \"bind\", String::class.java, callback)","handlingStrategy":"validation","validationCode":"for (Object o : parameterTypesAndCallback)\n    if (o != null && !(o instanceof XC_MethodHook)\n            && !(o instanceof Class) && !(o instanceof String))\n        throw new IllegalStateException(\"bad parameter type token: \" + o);","typeGuard":"static boolean isValidTypeToken(Object o) {\n    return o instanceof Class || o instanceof String;\n}","tryCatchPattern":"try {\n    XposedHelpers.findAndHookMethod(clazz, name, spec);\n} catch (XposedHelpers.ClassNotFoundError e) {\n    // spec contained a non-Class/String token; rewrite as Class or String\n}","preventionTips":["In Kotlin use String::class.java (never String::class / KClass).","Convert Type/TypeToken objects to Class yourself before building the varargs."],"tags":["xposed","android","type-mismatch","varargs","kotlin"],"backgroundTag":null,"analyzedSha":"df74d83eb03a44cc6ad268841ac2ada28d077c77","analyzedAt":"2026-08-14T10:46:48.326Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}