{"record":{"id":"0478ad677d334525","repo":"mobxjs/mobx","slug":"please-use-observable-accessor-string-context","errorCode":null,"errorMessage":"Please use `@observable accessor ${String(context.name)}` instead of `@observable ${String(context.name)}`","messagePattern":"Please use `@observable accessor (.+?)` instead of `@observable (.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mobx/src/types/observableannotation.ts","lineNumber":54,"sourceCode":"    proxyTrap: boolean\n): boolean | null {\n    assertObservableDescriptor(adm, this, key, descriptor)\n    return adm.defineObservableProperty_(\n        key,\n        descriptor.value,\n        this.options_?.enhancer_ ?? deepEnhancer,\n        proxyTrap\n    )\n}\n\nexport function decorateObservable20223_(\n    annotation: Annotation,\n    desc,\n    context: ClassAccessorDecoratorContext | ClassFieldDecoratorContext\n) {\n    if (__DEV__) {\n        if (context.kind === \"field\") {\n            throw die(\n                `Please use \\`@observable accessor ${String(\n                    context.name\n                )}\\` instead of \\`@observable ${String(context.name)}\\``\n            )\n        }\n        assert20223DecoratorType(context, [\"accessor\"])\n    }\n\n    const ann = annotation\n    const { kind, name } = context\n\n    if (kind !== \"accessor\") {\n        return\n    }\n\n    // Defer ObservableValue construction until first access. The factory is\n    // materialised by ObservableObjectAdministration on demand, so unused\n    // fields on wide classes never pay the per-instance allocation cost.","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx/src/types/observableannotation.ts#L36-L72","documentation":"In MobX 6.13+ with standard (non-legacy) decorators, @observable on a class field (decorator context kind === 'field') is no longer supported because native fields cannot be redefined; decorateObservable20223_ throws via die() directing you to the 'accessor' keyword. This applies to the 2022-3 (Stage 3) decorator transform only.","triggerScenarios":"Using native/Stage-3 decorators (TypeScript ~5 with 'experimentalDecorators' omitted/false, or Babel's 2023-11 decorator plugin) and declaring `@observable someField = value` on a class — MobX throws immediately at class definition time.","commonSituations":"Upgrading MobX to 6.13+ in a project using modern decorators without the legacy flag; new TypeScript 5 projects forgetting experimentalDecorators; copying legacy MobX decorator examples into a Stage-3 decorator codebase.","solutions":["Change the field to `@observable accessor someField = value` (requires @babel/plugin-proposal-decorators or TS supporting accessor).","Enable legacy decorators in tsconfig: { \"experimentalDecorators\": true, \"useDefineForClassFields\": false }.","Switch to makeObservable/makeAutoObservable without decorators.","Pin MobX < 6.13 temporarily if a full migration isn't possible (short-term only)."],"exampleFix":"// before (Stage-3 decorators)\nclass Store {\n  @observable count = 0\n}\n\n// after\nclass Store {\n  @observable accessor count = 0\n}","handlingStrategy":"validation","validationCode":"// tsconfig.json check before using @observable on fields with modern decorators:\n// { \"compilerOptions\": { \"experimentalDecorators\": true, \"useDefineForClassFields\": false } }\n// or, with Stage-3 decorators, require the accessor keyword:\nfunction assertAccessorDecorator(context) {\n  if (context.kind === 'field') {\n    throw new Error(`@observable requires 'accessor': use @observable accessor ${String(context.name)}`)\n  }\n  return context\n}","typeGuard":"function isAccessorContext(ctx) {\n  return ctx.kind === 'accessor'\n}","tryCatchPattern":"try {\n  defineStoreClass()\n} catch (e) {\n  if (String(e.message).includes('@observable accessor')) {\n    throw new Error('Migrate @observable fields to @observable accessor (Stage-3 decorators), or enable experimentalDecorators')\n  }\n  throw e\n}","preventionTips":["Use `@observable accessor` in all Stage-3 decorator codebases (MobX >= 6.13).","Keep experimentalDecorators: true + useDefineForClassFields: false if using legacy decorators.","Prefer makeAutoObservable in constructor to avoid decorator-mode pitfalls entirely.","Run the class-definition module in CI tests so decorator throws surface at build/test time."],"tags":["mobx","decorators","typescript","accessor","breaking-change","class-fields"],"backgroundTag":"observable-field-decorator-unsupported","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}