octobercms/october · error · Error

Invalid element for attach loader.

Error message

Invalid element for attach loader.

What it means

Thrown by resolveElement() in the AttachLoader extra of October CMS's larajax-based AJAX framework, reached via oc.attachLoader.show(el) / oc.attachLoader.hide(el). The helper accepts a DOM element or a CSS selector string; if a string is given it runs document.querySelector, and when the result is null (or the argument itself was null/undefined) it throws, because the loader cannot attach to a missing node.

Source

Thrown at modules/system/assets/js/framework-bundle.js:3071

        document.head.insertBefore(this.stylesheetElement, document.head.firstChild);
        _AttachLoader.stylesheetReady = true;
      }
    }
    createStylesheetElement() {
      const element = document.createElement("style");
      element.textContent = _AttachLoader.defaultCSS;
      return element;
    }
  };
  function isElementInput2(el) {
    return ["input", "select", "textarea"].includes((el.tagName || "").toLowerCase());
  }
  function resolveElement(el) {
    if (typeof el === "string") {
      el = document.querySelector(el);
    }
    if (!el) {
      throw new Error("Invalid element for attach loader.");
    }
    return el;
  }

  // ../../vendor/larajax/larajax/resources/src/extras/flash-message.js
  var FlashMessage = class _FlashMessage {
    static instance = null;
    static stylesheetReady = false;
    constructor() {
      this.queue = [];
      this.lastUniqueId = 0;
      this.displayedMessage = null;
      this.stylesheetElement = this.createStylesheetElement();
    }
    static get defaultCSS() {
      return unindent`
        .jax-flash-message {
            display: flex;

View on GitHub (pinned to b608633a7e)

Solutions

  1. Verify the selector matches exactly one existing node before calling: const el = document.querySelector(sel); if (el) oc.attachLoader.show(el)
  2. Pass the element reference you already have instead of re-querying a selector that may be stale
  3. Defer the call until the DOM is ready (oc.pageReady / DOMContentLoaded)
  4. In hide() paths, tolerate a missing node rather than throwing (guard with if (el))

Example fix

// before
oc.attachLoader.show('#save-btn');

// after
const btn = document.querySelector('#save-btn');
if (btn) oc.attachLoader.show(btn);
Defensive patterns

Strategy: validation

Validate before calling

function resolveLoaderTarget(ref) {
  const el = typeof ref === 'string' ? document.querySelector(ref) : ref;
  return el instanceof HTMLElement ? el : null;
}

const el = resolveLoaderTarget('#save-btn');
if (el) oc.attachLoader.show(el);

Type guard

const isHTMLElement = (v) => v instanceof HTMLElement || (v && v.nodeType === 1);

Try / catch

try { oc.attachLoader.show(ref); } catch (e) { if (/Invalid element for attach loader/.test(e.message)) { /* element gone: nothing to show on */ } else throw e; }

Prevention

When it happens

Trigger: oc.attachLoader.show('#save-btn') when no element matches #save-btn; passing a variable that is null (element already removed from the DOM, e.g. hide() called after an AJAX update replaced the container); calling show() before DOMContentLoaded so the selector matches nothing yet.

Common situations: Typos in selector strings; the target button living inside a partial that a previous AJAX response replaced (stale reference); scripts in <head> running before the body exists; dynamic lists where the row was deleted while a request was in flight.

Related errors


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