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
- Add `static get isReadOnlySupported() { return true; }` to each tool named in the message (only if the tool truly renders safely read-only)
- Replace/remove the unsupported tool
- 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
- Declare isReadOnlySupported on every custom tool
- Audit third-party tools before enabling read-only
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
- Unable to move Block down since it is already the last
- Unable to move Block up since it is already the first
- Incorrect data passed to the render() method
- Block with id "${id}" not found
- Block Tool with type "${newType}" not found
AI-assisted analysis of codex-team/editor.js@5f45dabbe5 (2026-08-27).
Data as JSON: /api/errors/541a270317e4a438.
Report an issue: GitHub.