{"record":{"id":"3356b0043d935e9d","repo":"karatelabs/karate","slug":"function-prototype-bind-called-on-non-callable","errorCode":null,"errorMessage":"Function.prototype.bind called on non-callable","messagePattern":"Function\\.prototype\\.bind called on non-callable","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsFunctionPrototype.java","lineNumber":132,"sourceCode":"        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        }\n        Object boundThis = args.length > 0 ? args[0] : Terms.UNDEFINED;\n        Object[] preBound = args.length > 1\n                ? Arrays.copyOfRange(args, 1, args.length)\n                : new Object[0];\n        JsFunction bound = new JsFunction() {\n            @Override\n            public Object call(Context ctx, Object[] callArgs) {\n                Object[] all;\n                if (preBound.length == 0) {\n                    all = callArgs;\n                } else {\n                    all = new Object[preBound.length + callArgs.length];\n                    System.arraycopy(preBound, 0, all, 0, preBound.length);\n                    System.arraycopy(callArgs, 0, all, preBound.length, callArgs.length);\n                }\n                if (ctx instanceof CoreContext cc) {\n                    cc.thisObject = boundThis;","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsFunctionPrototype.java#L114-L150","documentation":"Function.prototype.bind was invoked on a value that is not a JsCallable. bindMethod reads `this` from the context and, per §20.2.3.2, requires it to be a callable function; otherwise it throws a TypeError before constructing the bound function.","triggerScenarios":"Calling someValue.bind(this) where someValue is undefined, null, a plain object, a number/string, or a Java-exposed object that is not a JS function; destructuring a method off an object and binding it when the lookup failed.","commonSituations":"Callback registration code where the callback variable was never assigned; using .bind defensively on something assumed to be a function; refactors that replaced a function-typed field with a non-function value.","solutions":["Check typeof target === 'function' before calling bind().","Correct the variable/property so it actually references a function.","Use an arrow function closure instead of bind if you control the call site.","Guard with a default: `(target || function(){}).bind(this)` when a no-op is acceptable."],"exampleFix":"// before\nvar bound = maybeFn.bind(this); // TypeError if maybeFn is not a function\n// after\nvar bound = typeof maybeFn === 'function' ? maybeFn.bind(this) : function() {};","handlingStrategy":"type-guard","validationCode":"if (typeof target !== 'function') { throw new Error('bind target is not a function: ' + target); }","typeGuard":"function isBindable(v) { return v != null && typeof v.bind === 'function' && typeof v === 'function'; }","tryCatchPattern":"try { return target.bind(thisArg); } catch (e) { karate.log('bind failed on', target); return function() {}; }","preventionTips":["Guard optional callback parameters before binding","Prefer arrow functions over bind when the target is known at write time","Keep function-typed fields consistently typed through refactors"],"tags":["javascript","typeerror","function-prototype","bind"],"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"}