{"record":{"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":"validation","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/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-jasmine2/src/jasmine/spyRegistry.ts#L166-L202","documentation":"Thrown by SpyRegistry._spyOnProperty when the property descriptor has no member matching the requested accessType (spyRegistry.ts:183-189). For example spying with 'get' on a property that only has a setter, or with 'set' on a get-only accessor.","triggerScenarios":"spyOn(obj, 'readOnly', 'set') on a getter-only property, spyOn(obj, 'writeOnly', 'get') on a setter-only property, or passing an invalid accessType like 'value' for a property with no get/set.","commonSituations":"Confusing the two accessor directions; copy-paste of a get-spy for a set-only property; using the property-spy form on a plain data field whose descriptor has writable but no get/set.","solutions":["Inspect the descriptor and pick the matching accessType: Object.getOwnPropertyDescriptor(obj, 'p').","For plain data fields use spyOn(obj, 'p') without accessType.","For getter-only properties spy with 'get'; for setter-only spy with 'set'.","Add a test-time setter/getter via defineProperty if you need the other direction."],"exampleFix":"// before\nspyOn(store, 'readOnlyConfig', 'set'); // only a getter exists\n// after\nspyOn(store, 'readOnlyConfig', 'get');","handlingStrategy":"validation","validationCode":"const d = Object.getOwnPropertyDescriptor(obj, propertyName);\nif (!d || typeof d[accessType] !== 'function') {\n  throw new Error(`spyOn property: ${String(propertyName)} has no ${accessType} accessor`);\n}\nspyOn(obj, propertyName, accessType);","typeGuard":"type AccessType = 'get' | 'set';\nconst hasAccessor = (o: object, k: PropertyKey, at: AccessType): boolean => {\n  const d = Object.getOwnPropertyDescriptor(o, k);\n  return !!d && typeof d[at] === 'function';\n};","tryCatchPattern":null,"preventionTips":["Inspect the descriptor and choose get vs set accordingly.","Use plain spyOn for data fields.","Do not pass invalid accessType values."],"tags":["jest","spyon","mocking","property-accessor","access-type","api-misuse"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}