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

  1. Register the control before importing: oc.registerControl('myControl', MyControlClass)
  2. Check the Network/Console tabs: if the plugin's JS bundle 404s or throws, the registration never happens - fix the bundle first
  3. Make sure identifiers match exactly (case-sensitive) between oc.registerControl, oc.importControl, and data-control attributes
  4. 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

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


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/c63f7fcd88bc6023. Report an issue: GitHub.