{"id":"ebae0cd663276f2f","repo":"jestjs/jest","slug":"property-propertyname-does-not-have-access-type","errorCode":null,"errorMessage":"Property ${propertyName} does not have access type ${accessType}","messagePattern":"Property (.+?) does not have access type (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-jasmine2/src/jasmine/spyRegistry.ts","lineNumber":184,"sourceCode":"      let descriptor: PropertyDescriptor | undefined;\n      try {\n        descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);\n      } catch {\n        // IE 8 doesn't support `definePropery` on non-DOM nodes\n      }\n\n      if (!descriptor) {\n        throw new Error(getErrorMsg(`${propertyName} property does not exist`));\n      }\n\n      if (!descriptor.configurable) {\n        throw new Error(\n          getErrorMsg(`${propertyName} is not declared configurable`),\n        );\n      }\n\n      if (!descriptor[accessType]) {\n        throw new Error(\n          getErrorMsg(\n            `Property ${propertyName} does not have access type ${accessType}`,\n          ),\n        );\n      }\n\n      if (obj[propertyName] && isSpy(obj[propertyName])) {\n        if (this.respy) {\n          return obj[propertyName];\n        } else {\n          throw new Error(\n            getErrorMsg(`${propertyName} has already been spied upon`),\n          );\n        }\n      }\n\n      const originalDescriptor = descriptor;\n      const spiedProperty = createSpy(propertyName, descriptor[accessType]);","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-jasmine2/src/jasmine/spyRegistry.ts#L166-L202","documentation":"Thrown by `SpyRegistry._spyOnProperty` in spyRegistry.ts:184 when `descriptor[accessType]` is falsy — i.e. you asked to spy on the 'get' accessor but only a 'set' exists (or vice versa). `accessType` defaults to `'get'`.","triggerScenarios":"Calling `spyOnProperty(obj, 'writeOnly', 'get')` on a property that only has a setter; calling with the default 'get' on a write-only property; typo in the access type string.","commonSituations":"Write-only properties (rare); misunderstanding which accessor exists; defaulting to 'get' without checking the descriptor.","solutions":["Inspect the descriptor to see which accessor exists: `Object.getOwnPropertyDescriptor(obj, 'name')`.","Pass the matching access type: `spyOnProperty(obj, 'prop', 'set')` for a setter.","If the property is a plain data property (no accessors), use `spyOn` instead of `spyOnProperty`."],"exampleFix":"// before\nspyOnProperty(store, 'value', 'get') // only has setter\n// after\nspyOnProperty(store, 'value', 'set')","handlingStrategy":"validation","validationCode":"const d = Object.getOwnPropertyDescriptor(obj, propertyName);\nconst accessType = d?.get ? 'get' : d?.set ? 'set' : null;\nif (!accessType) { throw new Error('no accessor found'); }\nspyOnProperty(obj, propertyName, accessType);","typeGuard":"const pickAccessType = (d?: PropertyDescriptor): 'get' | 'set' | null =>\n  d?.get ? 'get' : d?.set ? 'set' : null;","tryCatchPattern":null,"preventionTips":["Inspect the descriptor before choosing the access type.","Use spyOn (not spyOnProperty) for plain data properties."],"tags":["jasmine2","spy","spy-on-property","accessor","get-set"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}