How to Resolve "TypeError: Cannot assign to read only property of object" Error in JavaScript
The TypeError: Cannot assign to read only property '...' of object is a common error in JavaScript that occurs when you attempt to modify a property that has been explicitly marked as non-writable. This safeguard is often used to prevent accidental or unintended modifications to objects, especially in the context of state management in libraries like React or Vue.
This guide will explain the two primary causes of this error: attempting to modify a frozen object and attempting to change a non-writable property descriptor. You will learn the correct, immutable patterns for working with these objects, such as creating copies, and how to properly define object properties to avoid this error.
Understanding the Root Cause: Non-Writable Properties
JavaScript allows object properties to be defined with specific attributes, one of which is writable. If writable is false, any attempt to change the property's value will fail, throwing a TypeError in strict mode. There are two main ways you can encounter a non-writable property.
Cause 1: Modifying a Frozen Object or Array
The most common cause of this error is using the Object.freeze() method. This method "freezes" an object, making all of its properties read-only and preventing any new properties from being added.
Example of error:
const user = {
name: 'John Doe',
};
// Freeze the object, making its properties read-only
Object.freeze(user);
// ⛔️ TypeError: Cannot assign to read only property 'name' of object '#<Object>'
user.name = 'Jane Doe';
The Error in Action (with an Array)
The same applies to arrays. Methods that mutate the array in place, like sort() or assigning to an index, will fail.
const letters = ['a', 'b', 'c'];
Object.freeze(letters);
// ⛔️ TypeError: Cannot assign to read only property '0' of object '[object Array]'
letters[0] = 'z';
// ⛔️ This also throws the same error because .sort() mutates the array
letters.sort();
Solution: Create a Copy Before Modifying
The correct way to work with a frozen object or array is to follow an immutable pattern: do not change the original; create a copy and change the copy.
Solution for Objects
Use the spread syntax (...) to create a shallow copy.
const user = { name: 'John Doe' };
Object.freeze(user);
// Create a copy of the user object
const newUser = { ...user };
// Modify the copy, not the original
newUser.name = 'Jane Doe';
console.log(newUser); // Output: { name: 'Jane Doe' }
console.log(user); // Output: { name: 'John Doe' } (original is unchanged)
Output:
{ name: 'Jane Doe' }
{ name: 'John Doe' }
Solution for Arrays
Use the spread syntax (...) or Array.prototype.slice() to create a shallow copy.
const letters = ['c', 'a', 'b'];
Object.freeze(letters);
// Create a copy before sorting
const sortedLetters = [...letters].sort();
console.log(sortedLetters); // Output: ['a', 'b', 'c']
console.log(letters); // Output: ['c', 'a', 'b'] (original is unchanged)
Cause 2: A Non-Writable Property Descriptor
The second cause of this error is when a property has been explicitly defined as non-writable using methods like Object.defineProperty() or Object.defineProperties().
The Error in Action
const config = {};
Object.defineProperty(config, 'VERSION', {
value: '1.0.0',
writable: false, // This is the default if not specified
enumerable: true,
configurable: true,
});
// ⛔️ TypeError: Cannot assign to read only property 'VERSION' of object '#<Object>'
config.VERSION = '1.0.1';
Solution: Set writable: true
If you are the author of the code defining the property, the solution is to explicitly allow the property to be changed by setting writable to true.
const config = {};
Object.defineProperty(config, 'VERSION', {
value: '1.0.0',
writable: true, // Allow this property to be changed
enumerable: true,
configurable: true,
});
// This now works without error
config.VERSION = '1.0.1';
console.log(config.VERSION); // Output: "1.0.1"
A Note on State Management Libraries (e.g., React)
You will frequently encounter this error when using state management libraries like React (with immutable state patterns) or Redux. These libraries often freeze their state objects to prevent you from modifying them directly.
This is a deliberate design choice. You are not supposed to mutate the state. Instead, you must use the provided functions (like a setState hook in React) to create a new state. The error is a helpful reminder to follow the correct pattern.
Conclusion
The "Cannot assign to read only property" error is a safeguard that prevents you from modifying objects that are intended to be immutable.
To fix it:
- If the object was frozen with
Object.freeze(), you must create a copy of the object or array (using{...}or[...]) and modify the copy. - If the property was defined with
Object.defineProperty(), you must ensure thewritable: trueattribute is set in its descriptor if you intend for it to be changeable. - If the error comes from a third-party library, it is likely a sign that you are trying to mutate an object that you shouldn't be. Look for the library's official method for updating its state.