mobxjs/mobx · warning
Found non-mobx decorator @${expr.name}
Error message
Found non-mobx decorator @${expr.name} What it means
The codemod only knows the mobx decorators that were used in `decorate(...)` calls it has seen. A single decorator on a member whose identifier is not in that known set is treated as a non-mobx (custom) decorator and skipped, since rewriting it would change semantics.
Source
Thrown at packages/mobx-undecorate/src/undecorate.ts:398
membersMap: [[any, any, boolean, boolean]]
},
clazzPath: ASTPath<ClassDeclaration>
): ClassProperty | ClassMethod {
const decorators = property.decorators
if (!decorators || decorators.length === 0) {
return property
}
if (decorators.length > 1) {
warn("Found multiple decorators, skipping..", property.decorators[0])
return property
}
const decorator = decorators[0]
if (!j.Decorator.check(decorator)) {
return property
}
let expr = decorator.expression
if (j.Identifier.check(expr) && !decoratorsUsed.has(expr.name)) {
warn(`Found non-mobx decorator @${expr.name}`, decorator)
return property
}
if (property.static) {
warn(`Static properties are not supported ${property.key.loc?.source}`, property)
return property
}
if (options?.keepDecorators !== true) {
property.decorators.splice(0)
}
// Replace decorator with @override
if ((property as any).override) {
const overrideDecorator = j.decorator(j.identifier("override"))
if (options?.keepDecorators) {
property.decorators[0] = overrideDecorator
}
expr = overrideDecorator.expressionView on GitHub (pinned to 01211a698b)
Solutions
- Register the decorator by adding it to a `decorate(MyClass, { member: yourDecorator })` call if it is actually a mobx-compatible decorator, then re-run the codemod.
- Remove or manually rewrite non-mobx decorators, converting their logic to explicit code.
- If it is a mobx decorator applied inline (no decorate call), convert the member manually to `makeObservable`.
Example fix
// before
@log count = 1
// after
constructor() { makeObservable(this, { count: observable }) }
// plus manual logging code
Defensive patterns
Strategy: validation
Validate before calling
const mobxDecorators = new Set(['observable','computed','action','flow','bound','override','autobind'])
const used = [...src.matchAll(/^\s*@([A-Za-z_$][\w$]*)/gm)].map(m => m[1])
const unknown = used.filter(n => !mobxDecorators.has(n))
if (unknown.length) console.warn('Non-mobx decorators present:', unknown) Type guard
function isMobxDecorator(name, decoratorsUsed) {
return typeof name === 'string' && decoratorsUsed.has(name)
} Prevention
- Register custom decorators via decorate(...) calls if they should be transformed
- Convert pure-custom decorators to plain code before migration
- Keep an inventory of which decorators in your codebase are mobx vs custom
When it happens
Trigger: A member decorated with an identifier (e.g. `@customlog foo`) that is not among the decorators collected from decorate calls — the identifier is not in `decoratorsUsed`.
Common situations: Custom project decorators (logging, formatting), decorators from non-mobx libraries, or mobx decorators used directly on class members without a corresponding `decorate` call so they were never registered in the known set.
Related errors
- Found multiple decorators, skipping..
- Static properties are not supported ${property.key.loc?.sour
- Unexpected type
- Expected a decorate call with two arguments
- Expected exactly one class declaration for '${target.name}'
AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28).
Data as JSON: /api/errors/4ff3c60be2ac3617.
Report an issue: GitHub.