codex-team/editor.js · critical · CriticalError

To enable read-only mode all connected tools should support

Error message

To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(', ')} don't support read-only mode.

What it means

ReadonlyMode.prepare/toggle checks every registered block tool for the isReadOnlySupported flag; if any tool lacks it, enabling read-only would silently break those tools, so a CriticalError is thrown listing the offending tools. CriticalError typically halts editor initialization.

Source

Thrown at src/components/modules/readonly.ts:124

    /**
     * Save current Editor Blocks and render again
     */
    const savedBlocks = await this.Editor.Saver.save();

    await this.Editor.BlockManager.clear();
    await this.Editor.Renderer.render(savedBlocks.blocks);

    this.Editor.ModificationsObserver.enable();

    return this.readOnlyEnabled;
  }

  /**
   * Throws an error about tools which don't support read-only mode
   */
  private throwCriticalError(): never {
    throw new CriticalError(
      `To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(', ')} don't support read-only mode.`
    );
  }
}

View on GitHub (pinned to 5f45dabbe5)

Solutions

  1. Add `static get isReadOnlySupported() { return true; }` to each tool named in the message (only if the tool truly renders safely read-only)
  2. Replace/remove the unsupported tool
  3. Keep readOnly off until all tools declare support

Example fix

// before
class MyTool {
  static get toolbox() { return {...}; }
}
// after
class MyTool {
  static get isReadOnlySupported() { return true; }
  static get toolbox() { return {...}; }
}
Defensive patterns

Strategy: validation

Validate before calling

const allSupport = Object.values(toolsConfig).every(t => (t as any).isReadOnlySupported === true); if (allSupport) editor.readOnly.toggle(true);

Type guard

const supportsReadOnly = (t: unknown): boolean => (t as any)?.isReadOnlySupported === true;

Try / catch

try { await editor.readOnly.toggle(true); } catch (e) { if (e instanceof CriticalError && e.message.includes('read-only mode')) { /* disable readOnly, patch tools */ return; } throw e; }

Prevention

When it happens

Trigger: Calling editor.readOnly.toggle(true) (or setting readOnly in a way that triggers prepare) while at least one tool (often a third-party one) does not declare `static get isReadOnlySupported() { return true; }`.

Common situations: Enabling read-only mode in an app using older/3rd-party tools (embeds, checkboxes, custom tools) that predate the read-only API; upgrading Editor.js and flipping readOnly on for the first time.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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