jestjs/jest · error · Error
Property `${propertyKey}` is not declared configurable
Error message
Property `${propertyKey}` is not declared configurable What it means
Thrown by _spyOnProperty when the descriptor for propertyKey is found but descriptor.configurable is false. JavaScript forbids redefining a non-configurable accessor, so the mocker cannot install a spy. Native properties and some frozen/sealed objects commonly have configurable:false.
Source
Thrown at packages/jest-mock/src/index.ts:1394
let descriptor = Object.getOwnPropertyDescriptor(object, propertyKey);
let proto = Object.getPrototypeOf(object);
while (!descriptor && proto !== null) {
descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
proto = Object.getPrototypeOf(proto);
}
if (!descriptor) {
throw new Error(
`Property \`${String(
propertyKey,
)}\` does not exist in the provided object`,
);
}
if (!descriptor.configurable) {
throw new Error(
`Property \`${String(propertyKey)}\` is not declared configurable`,
);
}
if (!descriptor[accessType]) {
throw new Error(
`Property \`${String(
propertyKey,
)}\` does not have access type ${accessType}`,
);
}
const original = descriptor[accessType];
if (!this.isMockFunction(original)) {
if (typeof original !== 'function') {
throw new TypeError(
`Cannot spy on the ${String(View on GitHub (pinned to f49721c78e)
Solutions
- Replace the target with a configurable stand-in: shallow-copy the object or wrap it before spying.
- Spy at the prototype level if the accessor is configurable there (or re-define it as configurable before spying, if you control the code).
- If you do not own the object, refactor the test to inject a seam (dependency injection) so you can pass a mockable instance.
Example fix
// before
jest.spyOn(frozenStore, 'version', 'get'); // frozenStore is Object.freeze'd
// after
const store = {...frozenStore}; Object.defineProperty(store, 'version', { configurable: true, get: () => 2 }); jest.spyOn(store, 'version', 'get'); Defensive patterns
Strategy: validation
Validate before calling
const d = Object.getOwnPropertyDescriptor(obj, key) ?? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), key);
if (!d || !d.configurable) {
throw new Error(`'${String(key)}' is not configurable; spy on a copy instead`);
}
jest.spyOn(obj, key, 'get'); Type guard
const isConfigurableAccessor = (o: object, k: PropertyKey, t: 'get' | 'set') => {
let d = Object.getOwnPropertyDescriptor(o, k);
let p = Object.getPrototypeOf(o);
while (!d && p) { d = Object.getOwnPropertyDescriptor(p, k); p = Object.getPrototypeOf(p); }
return !!(d?.configurable && d[t]);
}; Prevention
- Don't try to spy on frozen/sealed objects directly — operate on a copy.
- Avoid spying on built-in non-configurable properties like Array length.
- Inject a mockable seam via dependency injection when you don't own the object.
When it happens
Trigger: jest.spyOn([], 'length', 'get'); (Array.prototype.length is non-configurable); spying on a property of an Object.freeze'd object; spying on a built-in like Math.PI accessor; libraries that define hard-coded non-configurable accessors via Object.defineProperty(obj, k, {configurable:false, get}).
Common situations: Trying to mock readonly length of arrays/strings; targeting an object the application froze for safety; a third-party class that locks down its properties.
Related errors
- Property `${propertyKey}` does not exist in the provided obj
- Property `${propertyKey}` does not have access type ${access
- Cannot spy on the ${propertyKey} property because it is not
- Cannot use spyOn on a primitive value; ${typeOfObject} given
- No property name supplied
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/14585e7ff1e49ea3.json.
Report an issue: GitHub.