can1357/oh-my-pi · error · Error
Attribute not found: ${name}
Error message
Attribute not found: ${name} What it means
NamedNodeMap.removeNamedItem removes and returns the attribute with the given name; when getNamedItem finds no matching Attr it throws 'Attribute not found: <name>'. Unlike the standard DOM (which throws NotFoundError with a generic message and returns null in removeAttribute), this implementation surfaces the missing attribute name explicitly because removeNamedItem's contract requires returning the removed Attr.
Source
Thrown at packages/utils/src/dom/core.ts:434
export class NamedNodeMap extends Array<Attr> {
/** Find an attribute case-insensitively. */
getNamedItem(name: string): Attr | null {
const normalized = name.toLowerCase();
return this.find(attr => attr.name.toLowerCase() === normalized) ?? null;
}
/** Set an attribute object and return the prior one. */
setNamedItem(attr: Attr): Attr | null {
const previous = this.getNamedItem(attr.name);
if (previous) this.splice(this.indexOf(previous), 1, attr);
else this.push(attr);
return previous;
}
/** Remove and return a named attribute. */
removeNamedItem(name: string): Attr {
const attr = this.getNamedItem(name);
if (!attr) throw new Error(`Attribute not found: ${name}`);
this.splice(this.indexOf(attr), 1);
return attr;
}
}
/** Token-list view over an element class attribute. */
export class DOMTokenList implements Iterable<string> {
#element: Element;
constructor(element: Element) {
this.#element = element;
}
#tokens(): string[] {
return this.#element.className.trim() ? this.#element.className.trim().split(/\s+/) : [];
}
#write(tokens: string[]): void {View on GitHub (pinned to 9690622007)
Solutions
- Check existence first: `if (element.hasAttribute(name)) ...` before removeNamedItem.
- Prefer `element.removeAttribute(name)`, which is a no-op for missing attributes instead of throwing.
- Verify the exact attribute name/qualification (namespace prefix, case) via element.getAttributeNames().
- Make removal logic idempotent by catching the error or guarding with hasAttribute when processing possibly-already-cleaned nodes.
Example fix
// before: throws when attribute is absent
element.attributes.removeNamedItem("data-id");
// after: guard, or use removeAttribute
if (element.hasAttribute("data-id")) {
element.attributes.removeNamedItem("data-id");
}
// or simply:
element.removeAttribute("data-id"); // no-op if missing Defensive patterns
Strategy: validation
Validate before calling
if (element.hasAttribute(name)) {
element.attributes.removeNamedItem(name);
} Try / catch
try {
element.attributes.removeNamedItem(name);
} catch (err) {
if (err instanceof Error && err.message === `Attribute not found: ${name}`) {
// idempotent cleanup: attribute already absent — ignore
} else {
throw err;
}
} Prevention
- Prefer element.removeAttribute(name), which silently no-ops on missing attributes.
- Guard removals with hasAttribute or getAttributeNames() checks.
- Match attribute names exactly — including case and namespace prefixes — this map is name-sensitive.
When it happens
Trigger: Calling `element.attributes.removeNamedItem(name)` (or any API delegating to it) with an attribute name that the element does not have — typo'd name, wrong namespace-qualified form (e.g. 'xlink:href' vs 'href'), or the attribute was already removed.
Common situations: Best-effort attribute cleanup that assumes an attribute exists; case-sensitivity mismatches (attribute names are case-sensitive here); removing namespaced attributes using only the local name; scripts run twice so the second pass finds nothing to remove.
Related errors
- Plugin ${name} not found in runtime config
- Marketplace "${name}" not found
- Marketplace "${marketplace}" not found
- Plugin "${name}" not found in marketplace "${marketplace}"
- Plugin "${pluginId}" is not installed
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b26b5ff30b378f2a.
Report an issue: GitHub.