{"record":{"id":"4d908b8946bdcd6c","repo":"karatelabs/karate","slug":"unexpected-set-null-value-on-object","errorCode":null,"errorMessage":"unexpected set [null]:${value} on: ${object}","messagePattern":"unexpected set \\[null\\]:(.+?) on: (.+?)","errorType":"exception","errorClass":"JsErrorException (typeError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java","lineNumber":1142,"sourceCode":"     * when {@code Array.prototype.{push, unshift}} stores at index 0), routes\n     * {@code length} through {@code JsArray.handleLengthAssign} for the spec\n     * Uint32 + writable + partial-truncate dance, and otherwise falls through\n     * to {@code putMember}. Package-private so {@code JsArrayPrototype.{push,\n     * unshift}} can do per-item Set in the spec sequence.\n     */\n    static void setByName(Object object, String name, Object value, CoreContext context, Node trackingNode) {\n        setByName(object, name, value, context, trackingNode, object);\n    }\n\n    /** Receiver-aware variant for super references (§10.1.9 OrdinarySet with a\n     *  distinct receiver): the accessor lookup walks {@code object}'s chain —\n     *  the super base — but a setter runs with {@code receiver} as its\n     *  {@code this}, and a data write creates/updates the property on\n     *  {@code receiver}, never on the shared prototype. All non-super callers\n     *  pass {@code object} itself via the delegating overload above. */\n    static void setByName(Object object, String name, Object value, CoreContext context, Node trackingNode, Object receiver) {\n        if (name == null) {\n            throw JsErrorException.typeError(\"unexpected set [null]:\" + value + \" on: \" + object);\n        }\n        if (object == null) {\n            context.update(name, value, trackingNode);\n        } else if (object instanceof ObjectLike objectLike) {\n            // Spec ArraySetLength dispatch needs context for valueOf/toString\n            // coercion; route through the JsArray-specific entry point.\n            // Throws RangeError on invalid Uint32; silently ignores writable=false\n            // and partial-truncate failures (lenient mode — strict-mode TypeError\n            // flip lives elsewhere).\n            if (objectLike instanceof JsArray ja && \"length\".equals(name)) {\n                Object oldLen = ja.size();\n                ja.handleLengthAssign(value, context);\n                firePropertySet(context, name, ja.size(), oldLen, object, trackingNode);\n                return;\n            }\n            // If an accessor descriptor lives at `name` anywhere in the\n            // prototype chain, invoke its setter via slot.write —\n            // bypassing putMember preserves the descriptor and threads","sourceCodeStart":1124,"sourceCodeEnd":1160,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java#L1124-L1160","documentation":"An internal TypeError raised by Karate's setByName when the property name argument is null — i.e. an assignment whose target name could not be resolved to a string key. This is an invariant guard: normal `obj.x = v` syntax always supplies a name, so hitting it means the engine tried to write through a malformed/unresolved property reference (e.g. a computed key that evaluated to null in an internal path).","triggerScenarios":"A property-set operation routed into setByName with name == null: internal path where a computed/member key resolves to null, or a bridge/Embedded JS integration calling setByName programmatically with a null key.","commonSituations":"Rare in hand-written features; typically seen from custom JS engine extensions, external bridge integrations, or dynamic property writes where a key expression produced null instead of a string.","solutions":["Inspect the assignment expression in the feature/script and ensure the property key resolves to a non-null string (e.g. `obj[expr] = v` where `expr` must not be null).","Add a fallback for computed keys: `* def key = expr || 'defaultKey'` before `obj[key] = value`.","If calling the engine API directly, assert the name is non-null before calling setByName / update.","Report upstream if it occurs with plain syntax — it indicates an internal invariant violation."],"exampleFix":"// before (key may be null)\n* eval obj[someKey] = 5\n// after\n* def safeKey = someKey || 'fallback'\n* eval obj[safeKey] = 5","handlingStrategy":"validation","validationCode":"// before dynamic writes\nif (key == null) key = 'defaultKey';","typeGuard":"function safeKey(k) { return (k != null && typeof k === 'string') ? k : String(k); }","tryCatchPattern":null,"preventionTips":["Never assign via computed keys that can be null.","Coerce/null-check dynamic property names before writes.","If calling engine APIs directly, assert arguments before setByName/update."],"tags":["javascript","internal-invariant","property-write","null-key"],"backgroundTag":"internal-invariant-violation","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}