codex-team/editor.js · warning

EventDispatcher .off(): there is no subscribers for event "$

Error message

EventDispatcher .off(): there is no subscribers for event "${eventName.toString()}". Probably, .off() called before .on()

What it means

EventsDispatcher.off(eventName, callback) warns (console.warn, does not throw) when there are no subscribers at all for the event, which almost always means .off() was called before (or without) a matching .on(). The message includes the event name.

Source

Thrown at src/components/utils/events.ts:98

      return;
    }

    this.subscribers[eventName].reduce((previousData, currentHandler) => {
      const newData = currentHandler(previousData);

      return newData !== undefined ? newData : previousData;
    }, data);
  }

  /**
   * Unsubscribe callback from event
   *
   * @param eventName - event name
   * @param callback - event handler
   */
  public off<Name extends keyof EventMap>(eventName: Name, callback: Listener<EventMap[Name]>): void {
    if (this.subscribers[eventName] === undefined) {
      console.warn(`EventDispatcher .off(): there is no subscribers for event "${eventName.toString()}". Probably, .off() called before .on()`);

      return;
    }

    for (let i = 0; i < this.subscribers[eventName].length; i++) {
      if (this.subscribers[eventName][i] === callback) {
        delete this.subscribers[eventName][i];
        break;
      }
    }
  }

  /**
   * Destroyer
   * clears subscribers list
   */
  public destroy(): void {
    this.subscribers = {} as Subscriptions<EventMap>;

View on GitHub (pinned to 5f45dabbe5)

Solutions

  1. Ensure every off() has a matching prior on() with the same dispatcher and event name
  2. Subscribe in the same lifecycle that unsubscribes (e.g. onMounted/onUnmounted pairing)
  3. Guard with a check of the subscribers map or a flag before calling off

Example fix

// before
onUnmounted(() => dispatcher.off('blockChanged', handler)); // on() may never have run
// after
let subscribed = false;
onMounted(() => { dispatcher.on('blockChanged', handler); subscribed = true; });
onUnmounted(() => { if (subscribed) dispatcher.off('blockChanged', handler); });
Defensive patterns

Strategy: validation

Validate before calling

let subscribed = false; dispatcher.on('evt', handler); subscribed = true; if (subscribed) dispatcher.off('evt', handler);

Type guard

const hasSubscribers = (d: EventsDispatcher<any>, evt: string): boolean => Array.isArray((d as any).subscribers?.[evt]);

Prevention

When it happens

Trigger: Calling off('event', cb) before any on('event', ...); calling off on a different dispatcher instance than the one subscribed; unsubscribing after the component already cleared its subscribers.

Common situations: React/Vue cleanup functions running before mount subscription completed; duplicated components sharing state; ordering bugs in destroy() hooks.

Related errors


AI-assisted analysis of codex-team/editor.js@5f45dabbe5 (2026-08-27). Data as JSON: /api/errors/d409ff4bbf7d3213. Report an issue: GitHub.