{"record":{"id":"7537d5c358841f27","repo":"mobxjs/mobx","slug":"found-multiple-decorators-skipping","errorCode":null,"errorMessage":"Found multiple decorators, skipping..","messagePattern":"Found multiple decorators, skipping\\.\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/mobx-undecorate/src/undecorate.ts","lineNumber":389,"sourceCode":"        }\n    }\n\n    function handleProperty(\n        property: ClassProperty & /* | or ClassMethod */ {\n            decorators: Decorator[]\n            accessibility: \"private\" | \"protected\" | \"public\"\n        },\n        effects: {\n            membersMap: [[any, any, boolean, boolean]]\n        },\n        clazzPath: ASTPath<ClassDeclaration>\n    ): ClassProperty | ClassMethod {\n        const decorators = property.decorators\n        if (!decorators || decorators.length === 0) {\n            return property\n        }\n        if (decorators.length > 1) {\n            warn(\"Found multiple decorators, skipping..\", property.decorators[0])\n            return property\n        }\n        const decorator = decorators[0]\n        if (!j.Decorator.check(decorator)) {\n            return property\n        }\n        let expr = decorator.expression\n        if (j.Identifier.check(expr) && !decoratorsUsed.has(expr.name)) {\n            warn(`Found non-mobx decorator @${expr.name}`, decorator)\n            return property\n        }\n        if (property.static) {\n            warn(`Static properties are not supported ${property.key.loc?.source}`, property)\n            return property\n        }\n\n        if (options?.keepDecorators !== true) {\n            property.decorators.splice(0)","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx-undecorate/src/undecorate.ts#L371-L407","documentation":"The codemod can only translate properties/methods carrying a single mobx decorator. When a class member has more than one decorator, it cannot unambiguously rewrite them, so it warns and leaves the property untouched.","triggerScenarios":"`handleProperty` encounters a ClassProperty or ClassMethod whose `decorators.length > 1`, e.g. `@observable @action foo = ...` or `@computed @observable x`.","commonSituations":"Legacy MobX 4/5 code stacking decorators for logging/serialization alongside mobx decorators, or experimental decorator library mixes.","solutions":["Manually split the stacked decorators: keep mobx semantics in `makeObservable` and move other decorators (e.g. custom ones) to explicit code.","Run the codemod, then hand-fix the members reported with multiple decorators.","Reduce to a single mobx decorator before running the codemod where the combination was redundant."],"exampleFix":"// before\n@observable @reflect count = 1\n// after\nconstructor() { makeObservable(this, { count: observable }) }\n// then apply @reflect logic manually, e.g. via a setter or effect","handlingStrategy":"validation","validationCode":"const stacked = src.match(/@\\w+\\s+@\\w+/g) || []\nif (stacked.length) {\n  console.warn('Stacked decorators found, codemod will skip them:', stacked)\n}","typeGuard":"function hasSingleDecorator(member) {\n  return !member.decorators || member.decorators.length <= 1\n}","tryCatchPattern":null,"preventionTips":["Avoid stacking multiple decorators on one class member","Refactor stacked decorators to explicit code before migrating","Review codemod output for skipped members with multiple decorators"],"tags":["codemod","decorators","mobx-undecorate"],"backgroundTag":"codemod-skipped-unsupported-pattern","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}