karatelabs/karate · error · JsErrorException
Cannot assign to read only property
Error message
Cannot assign to read only property '{name}' What it means
failReadOnly is the shared strict-mode rejection helper for string-keyed properties: putMember detects a non-writable slot and calls it, throwing the standard 'Cannot assign to read only property' TypeError as mandated by strict-mode [[Set]].
Solutions
- Unfreeze the object or define the property writable:true if mutation is intended
- Create a mutable copy (structuredClone / spread) instead of mutating the frozen original
- Guard with Object.getOwnPropertyDescriptor check before writing
Example fix
// before
var o = Object.freeze({mode: 'x'});
o.mode = 'y'; // TypeError
// after
var o = {mode: 'x'}; // keep mutable, or clone before writing
var copy = {...o}; copy.mode = 'y'; Defensive patterns
Strategy: validation
Validate before calling
var d = Object.getOwnPropertyDescriptor(o, name); if (d && !d.writable) throw new TypeError('prop not writable: ' + name); Type guard
function isWritableProp(o, name) { var d = Object.getOwnPropertyDescriptor(o, name); return !d || d.writable === true; } Try / catch
try { o[name] = v; } catch (e) { if (String(e).includes('read only property')) { o = {...o, [name]: v}; } else { throw e; } } Prevention
- Don't freeze objects that are mutated downstream
- Always specify writable:true explicitly when using Object.defineProperty
- Clone frozen inputs before mutation
When it happens
Trigger: Strict-mode obj.prop = value (or obj[name] = value) where prop exists with writable:false, or the object is frozen with the property still present.
Common situations: Object.freeze on constants/config objects then mutating them; Object.defineProperty omitting writable (defaults false); mutating imported/module-level frozen objects; strict-mode modules/functions in the Karate JS engine.
Related errors
- Cannot assign to read only property
- Cannot add property , object is not extensible
- Cannot add property , object is not extensible
- Cannot delete property
- Cannot delete property
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/0a76460343fabe53.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsObject.java:478
/** Removes the tombstone for {@code name} if any. Subclasses use this when
* a write reanimates a previously-deleted entry. */
void clearTombstone(String name) {
PropertySlot s = props == null ? null : props.get(name);
if (s != null && s.tombstoned) {
props.remove(name);
}
}
/** True iff {@code name} has a non-tombstoned own slot (excludes intrinsics). */
boolean ownContainsKey(String name) {
PropertySlot s = props == null ? null : props.get(name);
return s != null && !s.tombstoned;
}
/** Strict-mode [[Set]] rejection: assigning a non-writable / frozen prop. */
static void failReadOnly(String name) {
throw JsErrorException.typeError("Cannot assign to read only property '" + name + "'");
}
/** Strict-mode [[Set]] rejection: adding a key to a non-extensible object. */
static void failNotExtensible(String name) {
throw JsErrorException.typeError("Cannot add property " + name + ", object is not extensible");
}
/** Strict-mode [[Delete]] rejection: removing a non-configurable property. */
static void failNotConfigurable(String name) {
throw JsErrorException.typeError("Cannot delete property '" + name + "' of " + "[object Object]");
}
@Override
public void putMember(String name, Object value) {
putMember(name, value, null, false);
}
@OverrideView on GitHub (pinned to a22eb90246)