mobxjs/mobx · warning

[mobx] Derivation ' ' is created/updated without reading…

Error message

[mobx] Derivation '${derivation.name_}' is created/updated without reading any observable value.

What it means

warnAboutDerivationWithoutDependencies fires when a derivation (computed or reaction body) completes tracking without reading any observable. Because it depends on nothing it will never re-run, which is almost always a bug, so MobX warns when reactionRequiresObservable is globally enabled or the derivation has requiresObservable_ set.

Solutions

  1. Make the derivation read at least one observable, or remove it if it needs no reactive inputs.
  2. Fix typos/wrong references so the body actually touches observable properties.
  3. Disable the global flag if intentional: configure({ reactionRequiresObservable: false }).
  4. For conditional bodies, hoist an observable read (e.g. store.ready) above the early return.
  5. Pass requiresObservable: true selectively only on derivations that must have deps.

Example fix

// before
autorun(() => {
  if (store.items.length === 0) return // fine, but reads nothing when guarded
  render(normalize(store.items))
})

// after
autorun(() => {
  const items = store.items // observable read first
  if (items.length === 0) return
  render(normalize(items))
})
Defensive patterns

Strategy: validation

Validate before calling

import { configure } from 'mobx'
// guard: every reaction body must read at least one observable
// configure({ reactionRequiresObservable: false }) // if legacy reactions read conditionally
function validateReactionBody(body) {
  const deps = new Set()
  const proxied = new Proxy(body, {})
  // simplest practical check: run under autorun with spy and assert an update event fires
  return typeof body === 'function' && body.length === 0
}

Prevention

When it happens

Trigger: Creating a reaction()/autorun() whose body reads no observables (e.g. reading plain JS fields, or reading before data is set up), or a computed that returns a constant, while configure({ reactionRequiresObservable: true }) or with requiresObservable: true on the decorator/observable options.

Common situations: Typo in property names inside a reaction body; reading from a plain (non-observable) object; reaction bodies guarded by an early return before any observable read; new teams enabling reactionRequiresObservable and hitting legacy reactions.

Related errors


AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28). Data as JSON: /api/errors/2795d3b9b7c3248b. Report an issue: GitHub.

Appendix: source

Thrown at packages/mobx/src/core/derivation.ts:215

    }
    return result
}

function warnAboutDerivationWithoutDependencies(derivation: IDerivation) {
    if (!__DEV__) {
        return
    }

    if (derivation.observing_.length !== 0) {
        return
    }

    if (
        typeof derivation.requiresObservable_ === "boolean"
            ? derivation.requiresObservable_
            : globalState.reactionRequiresObservable
    ) {
        console.warn(
            `[mobx] Derivation '${derivation.name_}' is created/updated without reading any observable value.`
        )
    }
}

/**
 * diffs newObserving with observing.
 * update observing to be newObserving with unique observables
 * notify observers that become observed/unobserved
 */
function bindDependencies(derivation: IDerivation) {
    // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
    const prevObserving = derivation.observing_
    const observing = (derivation.observing_ = derivation.newObserving_!)
    let lowestNewObservingDerivationState = IDerivationState_.UP_TO_DATE_

    // Go through all new observables and check diffValue: (this list can contain duplicates):
    //   0: first occurrence, change to 1 and keep it

View on GitHub (pinned to 01211a698b)