octobercms/october · error · Error
Control is not registered [${identifier}]
Error message
Control is not registered [${identifier}] What it means
Thrown by Application.import(identifier) in the observe (controls) layer of October CMS's larajax framework, exposed as oc.importControl(identifier). Controls used through data-control="..." attributes must first be registered with oc.registerControl(identifier, controlConstructor) (or app.register); import() looks the identifier up in the module container and throws when nothing was ever registered under that name.
Source
Thrown at modules/system/assets/js/framework-bundle.js:4366
register(identifier, controlConstructor) {
this.load({ identifier, controlConstructor });
}
observe(element, identifier) {
const observer = this.container.scopeObserver;
observer.elementMatchedValue(element, observer.parseValueForToken({
element,
content: identifier
}));
const foundControl = this.getControlForElementAndIdentifier(element, identifier);
if (!element.matches(`[data-control~="${identifier}"]`)) {
element.dataset.control = ((element.dataset.control || "") + " " + identifier).trim();
}
return foundControl;
}
import(identifier) {
const module = this.container.getModuleForIdentifier(identifier);
if (!module) {
throw new Error(`Control is not registered [${identifier}]`);
}
return module.controlConstructor;
}
fetch(element, identifier) {
if (typeof element === "string") {
element = document.querySelector(element);
}
if (!identifier) {
identifier = element.dataset.control;
}
return element ? this.getControlForElementAndIdentifier(element, identifier) : null;
}
fetchAll(elements, identifier) {
if (typeof elements === "string") {
elements = document.querySelectorAll(elements);
}
const result = [];
elements.forEach((element) => {View on GitHub (pinned to b608633a7e)
Solutions
- Register the control before importing: oc.registerControl('myControl', MyControlClass)
- Check the Network/Console tabs: if the plugin's JS bundle 404s or throws, the registration never happens - fix the bundle first
- Make sure identifiers match exactly (case-sensitive) between oc.registerControl, oc.importControl, and data-control attributes
- For optional/defensive lookups use oc.fetchControl(element, identifier) which returns null instead of throwing
Example fix
// before
const Ctl = oc.importControl('rich-editor'); // throws if never registered
// after
oc.registerControl('rich-editor', RichEditor);
const Ctl = oc.importControl('rich-editor'); Defensive patterns
Strategy: try-catch
Validate before calling
function safeImportControl(identifier) {
try {
return oc.importControl(identifier);
} catch {
return null; // not registered (bundle missing / not yet loaded)
}
} Type guard
const controlIsReachable = (el, identifier) => !!oc.fetchControl(el, identifier); // fetchControl returns null instead of throwing
Try / catch
try {
const Ctl = oc.importControl('rich-editor');
} catch (e) {
if (/Control is not registered/.test(e.message)) {
console.error(`Register '${'rich-editor'}' via oc.registerControl before importing`);
} else throw e;
} Prevention
- Register controls (oc.registerControl) in the same bundle that imports them, before the import runs
- Watch the Network tab for failed plugin bundles - a 404 means no registration happened
- Keep identifier casing identical across registerControl, importControl and data-control attributes
- Use oc.fetchControl for optional lookups - it returns null rather than throwing
When it happens
Trigger: Calling oc.importControl('dropdown') before any oc.registerControl('dropdown', Dropdown) ran; a data-control="myControl" element on the page while the plugin bundle that registers 'myControl' failed to load (404, JS error earlier in the bundle, wrong build); identifier case mismatch ('DropDown' vs 'dropdown').
Common situations: Plugin JS not loaded or loaded after the code that imports the control; registering in one bundle but importing from another with different timing; renaming a control class and forgetting the attribute/registration side; disabling a plugin whose script was expected to register the control.
Related errors
- Broken JSON boolean body near ${str}
- Invalid element for attach loader.
- Error parsing the ${name} attribute value. ${e}
- The request handler name is not specified.
- Invalid handler name. The correct handler name format is: "o
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/c63f7fcd88bc6023.
Report an issue: GitHub.