{"record":{"id":"8e9ab654573424ae","repo":"karatelabs/karate","slug":"function-prototype-apply-called-on-non-callable","errorCode":null,"errorMessage":"Function.prototype.apply called on non-callable","messagePattern":"Function\\.prototype\\.apply called on non-callable","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsFunctionPrototype.java","lineNumber":115,"sourceCode":"\n    // Spec OrdinaryCallBindThis (§9.2.1.2): the null/undefined → globalThis\n    // substitution applies to sloppy-mode user-defined functions only.\n    // Built-in methods and strict-mode user fns see the raw thisArg —\n    // required for e.g. Object.prototype.toString.call(null) returning\n    // \"[object Null]\" and for RequireObjectCoercible-gated built-ins to throw\n    // TypeError on null/undefined receivers.\n    private static Object bindForCall(JsCallable callable, Object thisObject, CoreContext cc) {\n        if (callable instanceof JsBuiltinMethod) {\n            return thisObject;\n        }\n        boolean strict = callable instanceof JsFunctionNode jfn && jfn.strict;\n        return Interpreter.bindThisForCall(thisObject, cc, strict);\n    }\n\n    private Object applyMethod(Context context, Object[] args) {\n        JsCallable callable = asCallable(context);\n        if (callable == null) {\n            throw JsErrorException.typeError(\"Function.prototype.apply called on non-callable\");\n        }\n        ThisArgs thisArgs = new ThisArgs(args, true);\n        if (context instanceof CoreContext cc) {\n            cc.thisObject = bindForCall(callable, thisArgs.thisObject, cc);\n        }\n        return callable.call(context, thisArgs.args.toArray(new Object[0]));\n    }\n\n    // Spec: Function.prototype.bind(thisArg, ...preBound) returns a new callable\n    // that, when invoked, calls the target with `this` set to thisArg and\n    // arguments = preBound concat actualArgs. Pre-bound args win in order.\n    // Per §20.2.3.2 the bound function's `length` is\n    // max(0, target.length - preBound.length).\n    private Object bindMethod(Context context, Object[] args) {\n        Object thisObj = context.getThisObject();\n        if (!(thisObj instanceof JsCallable target)) {\n            throw JsErrorException.typeError(\"Function.prototype.bind called on non-callable\");\n        }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsFunctionPrototype.java#L97-L133","documentation":"Function.prototype.apply was invoked on a value that is not a callable (function). Karate's JS engine implements Function.prototype.apply in JsFunctionPrototype.applyMethod, and per the ECMAScript spec it first coerces `this` to a callable; if that coercion fails (asCallable returns null) it throws a TypeError instead of failing later inside the interpreter.","triggerScenarios":"Calling fn.apply(...) where `fn` is undefined, null, a plain object, a primitive, or a non-function value that reached the Function prototype (e.g. a method borrowed from the wrong object, or a typo like `myfunc.aply` resolving through a proxy).","commonSituations":"Refactoring code where a variable that used to hold a function now holds its result; calling .apply on a Java-side value exposed to JS that is not wrapped as a JsCallable; duck-typed code assuming an object has a method that is actually missing.","solutions":["Print/inspect the value before calling apply and confirm it is a function (typeof fn === 'function').","Fix the reference so it points at the actual function instead of a call result or property lookup that returned undefined.","Use call() or spread (...) syntax instead if you do not need the apply argument-array semantics.","Wrap the invocation in try/catch if the callable is genuinely optional at runtime."],"exampleFix":"// before\nvar handler = config.handlers[name];\nhandler.apply(null, args); // handler may be undefined\n// after\nvar handler = config.handlers[name];\nif (typeof handler === 'function') {\n  handler.apply(null, args);\n} else {\n  karate.log('no handler for', name);\n}","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') { throw new Error('expected callable, got: ' + fn); }","typeGuard":"function isCallable(v) { return typeof v === 'function'; }","tryCatchPattern":"try { fn.apply(thisArg, args); } catch (e) { if (String(e).indexOf('non-callable') !== -1) { karate.log('not a function:', fn); } else { throw e; } }","preventionTips":["Always verify typeof === 'function' before apply/call/bind on dynamic references","Avoid naming collisions that shadow function-valued variables with their results","Wrap Java-side values and confirm they are exposed as JS functions before treating them as callables"],"tags":["javascript","typeerror","function-prototype"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}