{"record":{"id":"545fd29eaa14d3fe","repo":"karatelabs/karate","slug":"cannot-add-property-sym-object-is-not-extensible","errorCode":null,"errorMessage":"Cannot add property {sym}, object is not extensible","messagePattern":"Cannot add property (.+?), object is not extensible","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsObject.java","lineNumber":245,"sourceCode":"                acc.write(this, value, ctx, strict);\n                return;\n            }\n            if (!s.isWritable()) {\n                if (strict) {\n                    throw JsErrorException.typeError(\n                            \"Cannot assign to read only property '\" + sym + \"'\");\n                }\n                return;\n            }\n            if (jo == this) {\n                s.write(this, value, ctx, strict);\n                return;\n            }\n            break; // inherited writable data property — shadow it with an own slot\n        }\n        if (frozen || sealed || nonExtensible) {\n            if (strict) {\n                throw JsErrorException.typeError(\n                        \"Cannot add property \" + sym + \", object is not extensible\");\n            }\n            return;\n        }\n        defineOwnSymbol(sym, value, PropertySlot.ATTRS_DEFAULT);\n    }\n\n    /** Low-level data-descriptor write for a symbol key — the\n     *  {@code Object.defineProperty} seam. */\n    void defineOwnSymbol(JsSymbol sym, Object value, byte attrs) {\n        if (symbols == null) {\n            symbols = new LinkedHashMap<>(4);\n        }\n        PropertySlot existing = symbols.get(sym);\n        DataSlot s;\n        if (existing instanceof DataSlot ds) {\n            s = ds;\n        } else {","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsObject.java#L227-L263","documentation":"Strict-mode [[Set]] on a new property requires the object to be extensible. When the receiver (or a prototype in the chain) is frozen, sealed, or non-extensible, adding a brand-new symbol-keyed property throws a TypeError in strict mode and is silently skipped otherwise.","triggerScenarios":"Strict-mode obj[newSymbol] = value where obj was produced by Object.freeze/Object.seal/Object.preventExtensions (or an ancestor with only inherited writable props blocked that way).","commonSituations":"Freezing config or shared objects and later attaching symbol-keyed caches/metadata; freezing objects in tests to detect accidental mutation; framework-created frozen objects.","solutions":["Don't freeze/seal the object if new symbol properties must be added","Pre-define the needed symbol properties before freezing","Use a WeakMap keyed by the object instead of symbol properties for extra metadata"],"exampleFix":"// before\nvar cfg = Object.freeze({a: 1});\ncfg[metaSym] = 'x'; // TypeError\n// after\nvar meta = new WeakMap();\nmeta.set(cfg, 'x');","handlingStrategy":"validation","validationCode":"if (!Object.isExtensible(o)) throw new TypeError('cannot add symbol prop to non-extensible object');","typeGuard":"function canAddProp(o) { return Object.isExtensible(o); }","tryCatchPattern":"try { o[sym] = v; } catch (e) { if (String(e).includes('not extensible')) { metaMap.set(o, v); } else { throw e; } }","preventionTips":["Prefer WeakMap for attaching data to frozen objects","Freeze objects only after all properties (including symbol slots) are defined","Check Object.isExtensible before adding new keys in strict code"],"tags":["javascript","strict-mode","typeerror","frozen-object","karate-js"],"backgroundTag":"object-not-extensible","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"}