{"id":"126aa1148289086b","repo":"jestjs/jest","slug":"property-propertykey-does-not-have-access-typ","errorCode":null,"errorMessage":"Property `${propertyKey}` does not have access type ${accessType}","messagePattern":"Property `(.+?)` does not have access type (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-mock/src/index.ts","lineNumber":1400,"sourceCode":"      proto = Object.getPrototypeOf(proto);\n    }\n\n    if (!descriptor) {\n      throw new Error(\n        `Property \\`${String(\n          propertyKey,\n        )}\\` does not exist in the provided object`,\n      );\n    }\n\n    if (!descriptor.configurable) {\n      throw new Error(\n        `Property \\`${String(propertyKey)}\\` is not declared configurable`,\n      );\n    }\n\n    if (!descriptor[accessType]) {\n      throw new Error(\n        `Property \\`${String(\n          propertyKey,\n        )}\\` does not have access type ${accessType}`,\n      );\n    }\n\n    const original = descriptor[accessType];\n\n    if (!this.isMockFunction(original)) {\n      if (typeof original !== 'function') {\n        throw new TypeError(\n          `Cannot spy on the ${String(\n            propertyKey,\n          )} property because it is not a function; ${this._typeOf(\n            original,\n          )} given instead.${\n            typeof original === 'object'\n              ? ''","sourceCodeStart":1382,"sourceCodeEnd":1418,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-mock/src/index.ts#L1382-L1418","documentation":"Thrown by _spyOnProperty when the descriptor exists and is configurable but lacks the requested accessType — i.e. you asked to spy 'get' on a write-only accessor (only has set), or 'set' on a read-only accessor (only has get). The check is !descriptor[accessType].","triggerScenarios":"jest.spyOn(obj, 'readOnlyProp', 'set') where the property has only a getter; jest.spyOn(obj, 'writeOnlyProp', 'get') where it has only a setter. Common with computed properties that intentionally expose only one direction.","commonSituations":"Assuming every accessor is a full get/set pair; library design where a property is intentionally write-only (e.g. credentials) or read-only.","solutions":["Spy on the access type the property actually defines: use 'get' for read-only, 'set' for write-only.","Inspect the descriptor first: Object.getOwnPropertyDescriptor(obj, key) and check which of get/set are present.","If you need to control both directions, redefine the property (if configurable) to have both, then spy on each."],"exampleFix":"// before\njest.spyOn(user, 'id', 'set'); // id is read-only\n// after\njest.spyOn(user, 'id', 'get');","handlingStrategy":"validation","validationCode":"const d = Object.getOwnPropertyDescriptor(obj, key);\nif (!d || !d['get']) {\n  throw new Error(`'${String(key)}' has no getter; cannot spy with 'get'`);\n}\njest.spyOn(obj, key, 'get');","typeGuard":"const hasAccessType = (o: object, k: PropertyKey, t: 'get' | 'set'): boolean => {\n  let d = Object.getOwnPropertyDescriptor(o, k);\n  let p = Object.getPrototypeOf(o);\n  while (!d && p) { d = Object.getOwnPropertyDescriptor(p, k); p = Object.getPrototypeOf(p); }\n  return !!(d && typeof d[t] === 'function');\n};\n\nconst access = hasAccessType(obj, key, 'get') ? 'get' : 'set';\njest.spyOn(obj, key, access);","tryCatchPattern":null,"preventionTips":["Inspect which of get/set the property actually exposes before spying.","Remember read-only properties only have 'get', write-only only have 'set'.","If you need both, redefine the property to include both directions (if configurable)."],"tags":["jest-mock","spyon","accessor","get-set-mismatch"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}