{"record":{"id":"b26b5ff30b378f2a","repo":"can1357/oh-my-pi","slug":"attribute-not-found-name","errorCode":null,"errorMessage":"Attribute not found: ${name}","messagePattern":"Attribute not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/dom/core.ts","lineNumber":434,"sourceCode":"export class NamedNodeMap extends Array<Attr> {\n\t/** Find an attribute case-insensitively. */\n\tgetNamedItem(name: string): Attr | null {\n\t\tconst normalized = name.toLowerCase();\n\t\treturn this.find(attr => attr.name.toLowerCase() === normalized) ?? null;\n\t}\n\n\t/** Set an attribute object and return the prior one. */\n\tsetNamedItem(attr: Attr): Attr | null {\n\t\tconst previous = this.getNamedItem(attr.name);\n\t\tif (previous) this.splice(this.indexOf(previous), 1, attr);\n\t\telse this.push(attr);\n\t\treturn previous;\n\t}\n\n\t/** Remove and return a named attribute. */\n\tremoveNamedItem(name: string): Attr {\n\t\tconst attr = this.getNamedItem(name);\n\t\tif (!attr) throw new Error(`Attribute not found: ${name}`);\n\t\tthis.splice(this.indexOf(attr), 1);\n\t\treturn attr;\n\t}\n}\n\n/** Token-list view over an element class attribute. */\nexport class DOMTokenList implements Iterable<string> {\n\t#element: Element;\n\n\tconstructor(element: Element) {\n\t\tthis.#element = element;\n\t}\n\n\t#tokens(): string[] {\n\t\treturn this.#element.className.trim() ? this.#element.className.trim().split(/\\s+/) : [];\n\t}\n\n\t#write(tokens: string[]): void {","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/dom/core.ts#L416-L452","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: throws when attribute is absent\nelement.attributes.removeNamedItem(\"data-id\");\n\n// after: guard, or use removeAttribute\nif (element.hasAttribute(\"data-id\")) {\n  element.attributes.removeNamedItem(\"data-id\");\n}\n// or simply:\nelement.removeAttribute(\"data-id\"); // no-op if missing","handlingStrategy":"validation","validationCode":"if (element.hasAttribute(name)) {\n  element.attributes.removeNamedItem(name);\n}","typeGuard":null,"tryCatchPattern":"try {\n  element.attributes.removeNamedItem(name);\n} catch (err) {\n  if (err instanceof Error && err.message === `Attribute not found: ${name}`) {\n    // idempotent cleanup: attribute already absent — ignore\n  } else {\n    throw err;\n  }\n}","preventionTips":["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."],"tags":["dom","attributes","not-found"],"backgroundTag":"dom-attribute-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}