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
- Verify the selector matches exactly one existing node before calling: const el = document.querySelector(sel); if (el) oc.attachLoader.show(el)
- Pass the element reference you already have instead of re-querying a selector that may be stale
- Defer the call until the DOM is ready (oc.pageReady / DOMContentLoaded)
- 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
- Check the element exists before calling show()/hide()
- Pass element references, not selectors, around AJAX updates that replace the DOM
- Run loader calls after DOM ready (oc.pageReady)
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
- Broken JSON boolean body near ${str}
- Control is not registered [${identifier}]
- 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/3351fbaf849a1ec6.
Report an issue: GitHub.