karatelabs/karate · error · JsErrorException
Map.prototype.getOrInsertComputed: callback is not a…
Error message
Map.prototype.getOrInsertComputed: callback is not a function
What it means
`Map.prototype.getOrInsertComputed(key, callback)` (upsert proposal) invokes the callback only when the key is absent, but the callback itself must be a function. Karate throws this TypeError when args[1] is missing or not a JsCallable.
Solutions
- Pass a function as the second argument: `map.getOrInsertComputed('k', () => compute())`
- If you have a plain value, use `map.getOrInsert('k', value)` instead
- Check that the callback variable resolves to a function, not its name/string
Example fix
// before
map.getOrInsertComputed('key', 42); // TypeError
// after
map.getOrInsertComputed('key', () => 42); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof cb !== 'function') { throw new Error('getOrInsertComputed requires a function callback'); } Type guard
function isFn(x) { return typeof x === 'function'; } Try / catch
try {
m.getOrInsertComputed(key, cb);
} catch (e) {
if (String(e.message).includes('callback is not a function')) {
m.getOrInsert(key, cb); // maybe a plain value was intended
} else throw e;
} Prevention
- Remember: Computed variant takes a function, getOrInsert takes a value
- Wrap lazily computed defaults: () => expensiveCompute()
- Resolve dynamic callbacks before the call
When it happens
Trigger: `map.getOrInsertComputed('k')` without the callback; passing a value instead of a function (`map.getOrInsertComputed('k', 42)`); passing a function name string from config instead of the function itself.
Common situations: Confusing getOrInsertComputed with getOrInsert (which takes a plain value); refactors that swapped the two APIs; dynamically loaded callbacks that failed to resolve.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Map.prototype.forEach: callback is not a function
- callback is not a function
- Constructor Map requires 'new'
- filter() needs two arguments: list and function
- filterKeys() needs at least two arguments
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/ac0732645d1fc2bc.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsMapPrototype.java:162
m.setValue(key, value);
return value;
}
/**
* Spec ES2025 upsert: {@code getOrInsertComputed(key, callbackfn)}. If the
* key is present, returns the existing value WITHOUT invoking the callback
* (does-not-evaluate-callbackfn-if-key-present.js). Otherwise calls
* {@code callbackfn(canonicalKey)} (canonical-key-passed-to-callback.js)
* and stores the result. Re-checks key presence after the callback returns
* so a callback that mutates the map can't leave a stale insert
* (overwrites-mutation-from-callbackfn.js).
*/
private Object getOrInsertComputed(Context context, Object[] args) {
JsMap m = asMap(context);
Object key = args.length > 0 ? args[0] : Terms.UNDEFINED;
Object cb = args.length > 1 ? args[1] : Terms.UNDEFINED;
if (!(cb instanceof JsCallable callable)) {
throw JsErrorException.typeError("Map.prototype.getOrInsertComputed: callback is not a function");
}
if (m.hasKey(key)) {
return m.getValue(key);
}
// Canonical key: spec normalizes -0 to +0 before invoking callback.
Object canonicalKey = JsMap.normalizeKey(key);
Object value = callable.call(context, new Object[]{canonicalKey});
// Spec: a callback that threw stops the operation. The engine signals
// throws via {@code cc.error}; bail without inserting so post-throw
// {@code map.has(key) === false} (check-state-after-callback-fn-throws.js).
CoreContext cc = context instanceof CoreContext c ? c : null;
if (cc != null && cc.isError()) {
return Terms.UNDEFINED;
}
// Java-null callback returns surface to JS as undefined. Re-checking
// map state after the callback returned: per spec, OVERWRITE any
// entry the callback inserted at the same key
// (overwrites-mutation-from-callbackfn.js).View on GitHub (pinned to a22eb90246)