Logix

Troubleshooting

Logix diagnostic codes explained, with common failure scenarios and fixes.

This page collects diagnostic codes emitted by the Logix Runtime, common failure scenarios, and how to fix them.

Who is this for?

  • You hit Logix errors/warnings and want to quickly find the root cause.
  • You see diagnostic events in DevTools and want to understand what they mean.

Prerequisites

  • You’ve read “Modules & State” and “Flows & Effects” and understand the basic Module/Logic structure.

What you’ll get

  • Quickly locate root causes based on diagnostic codes.
  • Fix the most common setup/run phase mistakes.

Diagnostic code cheat sheet

CodeSeverityMeaningFix direction
logic::invalid_phaseerrorAPI used in wrong phasemove the call into the correct phase
logic::env_service_not_foundwarningEnv service not ready (common startup noise)check Layer provisioning order
assembly::missing_module_runtimeerrormissing imports/scope for a child moduleprovide imports or a root singleton
reducer::late_registrationwarningReducer registered latemove $.reducer into setup
state_transaction::dirty_all_fallbackwarningmissing field-level dirty evidenceprefer $.state.mutate / immerReducers / ModuleTag.Reducer.mutate
state_transaction::async_escapeerrorasync/await escaped txn windowno IO/await inside a synchronous transaction; use run*Task or split entries
state_transaction::enqueue_in_transactionerrordispatch/setState inside txn windowmove dispatch outside the transaction window; use a multi-entry pattern
logic::invalid_usageerrorrun*Task called inside txn windowcall run*Task from watcher run section, not inside reducers/update/mutate bodies

Common failure scenarios

1. LogicPhaseError: calling $.lifecycle.* in run phase

Symptom:

[LogicPhaseError] $.lifecycle.onInit is not allowed in run phase (kind=lifecycle_in_run).

Diagnostic code: logic::invalid_phase

Cause: lifecycle registration APIs like $.lifecycle.onInit / $.lifecycle.onDestroy are setup-only. They must be called in the setup phase of the Logic builder (before return), not inside Effect.gen.

Incorrect:

const Logic = Module.logic(($) =>
  Effect.gen(function* () {
    // ❌ This is run phase: lifecycle registration is not allowed here
    $.lifecycle.onInit(Effect.log('init'))

    yield* $.onAction('foo').run(/* ... */)
  }),
)

Correct:

const Logic = Module.logic(($) => {
  // ✅ Setup phase: before return
  $.lifecycle.onInit(Effect.log('init'))

  return Effect.gen(function* () {
    // Run phase: write watchers as usual
    yield* $.onAction('foo').run(/* ... */)
  })
})

2. LogicPhaseError: calling $.use in setup phase

Symptom:

[LogicPhaseError] $.use is not allowed in setup phase (kind=use_in_setup).

Diagnostic code: logic::invalid_phase

Cause: $.use(Service) reads dependencies from the runtime environment, so it can only be called in run phase (inside Effect.gen).

Incorrect:

const Logic = Module.logic(($) => {
  // ❌ Setup phase can't access Env
  const api = $.use(ApiService)

  return Effect.gen(function* () {
    /* ... */
  })
})

Correct:

const Logic = Module.logic(($) =>
  Effect.gen(function* () {
    // ✅ Run phase: yield* $.use is allowed
    const api = yield* $.use(ApiService)
    // ...
  }),
)

3. MissingModuleRuntimeError: missing imports

Symptom:

MissingModuleRuntimeError: Module 'Child' is not available in imports.

Cause: Logic tries to access a child module via $.use(ChildModule), but the module was not provided in imports when calling implement.

Incorrect:

const HostModule = HostDef.implement({
  initial: {
    /* ... */
  },
  logics: [HostLogic],
  // ❌ Missing imports
})

Correct:

const HostModule = HostDef.implement({
  initial: {
    /* ... */
  },
  logics: [HostLogic],
  imports: [ChildImpl], // ✅ Provide the child module implementation
})

4. Reducer registered too late

Symptoms:

  • After dispatching an Action, the primary reducer did not run.
  • DevTools shows a reducer::late_registration warning.

Diagnostic code: reducer::late_registration

Cause: $.reducer(tag, fn) must be called in setup phase; reducers registered in run phase are not executed by the Runtime.

Incorrect:

const Logic = Module.logic(($) =>
  Effect.gen(function* () {
    // ❌ Registering reducers in run phase won't work
    $.reducer('increment', (s) => ({ ...s, count: s.count + 1 }))
  }),
)

Correct:

const Logic = Module.logic(($) => {
  // ✅ Register reducers in setup phase
  $.reducer('increment', (s) => ({ ...s, count: s.count + 1 }))

  return Effect.gen(function* () {
    /* ... */
  })
})

Recommended: put the primary reducer directly in the reducers field of Logix.Module.make.


5. Declaring traits in run phase

Symptom:

[LogicPhaseError] $.traits.declare is not allowed in run phase (kind=traits_declare_in_run).

Diagnostic code: logic::invalid_phase

Cause: $.traits.declare(...) is setup-only. Traits are frozen after setup ends.

Correct:

const Logic = Module.logic(($) => ({
  setup: Effect.sync(() => {
    // ✅ Declare traits in setup phase
    $.traits.declare({
      /* ... */
    })
  }),
  run: Effect.void,
}))

6. “Service not found” noise during init

Symptoms:

  • You see Service not found: ... warnings at app startup.
  • Everything works fine afterwards.

Diagnostic code: logic::env_service_not_found

Cause: during init, Logic attempts to access an Env service that is not fully provisioned yet. Under certain initialization orders, this can be a known one-time noise.

What to do:

  • If it happens only once on startup and the app works afterwards, you can ignore it.
  • If it keeps happening, verify Runtime.make / RuntimeProvider.layer correctly provides the service.

DevTools diagnostic events

When DevTools is enabled (devtools: true), all diagnostic events appear in the timeline with type diagnostic.

Typical event shape:

{
  type: 'diagnostic',
  moduleId: 'Counter',
  code: 'logic::invalid_phase',
  severity: 'error',
  message: '$.lifecycle.onInit is not allowed in run phase.',
  hint: 'Do not register $.lifecycle.* in run phase (setup-only). Move lifecycle registration into the synchronous part of the Module.logic builder (before return).',
  kind: 'lifecycle_in_run'
}
  • code: diagnostic code (use the cheat sheet to locate)
  • severity: error / warning / info
  • hint: fix suggestion

Next

On this page