swc-project/swc · error · anyhow::Error

failed to parse namespace of context element

Error message

failed to parse namespace of context element

What it means

Same logic as the Node binding, compiled into the WebAssembly HTML binding: create_namespace accepts exactly six well-known namespace URIs (XHTML, MathML, SVG, XLINK, XML, XMLNS), compared lowercased, when converting the JS-side context element for fragment parsing. Any other namespace string on the element or its attributes fails before parsing begins; the error then crosses the wasm boundary as a JS exception.

Source

Thrown at bindings/binding_html_wasm/src/lib.rs:278

const fn default_collapse_whitespaces() -> CollapseWhitespaces {
    CollapseWhitespaces::OnlyMetadata
}

enum DocumentOrDocumentFragment {
    Document(Document),
    DocumentFragment(DocumentFragment),
}

fn create_namespace(namespace: &str) -> anyhow::Result<Namespace> {
    match &*namespace.to_lowercase() {
        "http://www.w3.org/1999/xhtml" => Ok(Namespace::HTML),
        "http://www.w3.org/1998/math/mathml" => Ok(Namespace::MATHML),
        "http://www.w3.org/2000/svg" => Ok(Namespace::SVG),
        "http://www.w3.org/1999/xlink" => Ok(Namespace::XLINK),
        "http://www.w3.org/xml/1998/namespace" => Ok(Namespace::XML),
        "http://www.w3.org/2000/xmlns/" => Ok(Namespace::XMLNS),
        _ => {
            bail!("failed to parse namespace of context element")
        }
    }
}

fn create_element(context_element: Element) -> anyhow::Result<swc_html_ast::Element> {
    let mut attributes = Vec::with_capacity(context_element.attributes.len());

    for attribute in context_element.attributes.into_iter() {
        let namespace = match attribute.namespace {
            Some(namespace) => Some(create_namespace(&namespace)?),
            _ => None,
        };

        attributes.push(swc_html_ast::Attribute {
            span: DUMMY_SP,
            namespace,
            prefix: attribute.prefix.map(|value| value.into()),
            name: attribute.name.into(),

View on GitHub (pinned to 5176682b65)

Solutions

  1. Normalize namespaces to one of the six exact URIs before calling the API (only 'http://www.w3.org/2000/xmlns/' ends with a slash)
  2. Omit namespace for un-namespaced elements and attributes
  3. Filter or map unknown namespaces from context elements produced by upstream parsers

Example fix

// before
contextElement = { tagName: 'svg', namespace: el.namespaceURI };
// el.namespaceURI could be anything DOMParser produced

// after
const KNOWN = new Set([
  'http://www.w3.org/1999/xhtml',
  'http://www.w3.org/1998/math/mathml',
  'http://www.w3.org/2000/svg',
  'http://www.w3.org/1999/xlink',
  'http://www.w3.org/xml/1998/namespace',
  'http://www.w3.org/2000/xmlns/',
]);
contextElement = {
  tagName: 'svg',
  namespace: KNOWN.has(el.namespaceURI) ? el.namespaceURI : undefined,
};
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = new Set([
  'http://www.w3.org/1999/xhtml',
  'http://www.w3.org/1998/math/mathml',
  'http://www.w3.org/2000/svg',
  'http://www.w3.org/1999/xlink',
  'http://www.w3.org/xml/1998/namespace',
  'http://www.w3.org/2000/xmlns/',
]);
function sanitizeContextElement(el) {
  const ns = el.namespace?.toLowerCase();
  if (ns && !KNOWN.has(ns)) delete el.namespace;
  el.attributes = (el.attributes ?? []).map((a) => {
    if (a.namespace && !KNOWN.has(a.namespace.toLowerCase())) {
      const { namespace, ...rest } = a;
      return rest;
    }
    return a;
  });
  return el;
}

Type guard

const isKnownNamespace = (ns: string): boolean =>
  [
    'http://www.w3.org/1999/xhtml',
    'http://www.w3.org/1998/math/mathml',
    'http://www.w3.org/2000/svg',
    'http://www.w3.org/1999/xlink',
    'http://www.w3.org/xml/1998/namespace',
    'http://www.w3.org/2000/xmlns/',
  ].includes(ns.toLowerCase());

Try / catch

try {
  const res = await parse(src, { contextElement });
} catch (e) {
  if (String(e?.message).includes('namespace of context element')) {
    return parse(src, { contextElement: sanitizeContextElement(contextElement) });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the wasm HTML parse API in fragment mode with options.contextElement (or an attribute on it) whose namespace is not one of the six exact URIs, e.g. 'http://www.w3.org/2000/svg/' with a trailing slash or a custom namespace URI.

Common situations: Browser or bundler-integrated tooling reusing context elements parsed by other libraries (DOMParser, parse5) that carry extra namespaces; typos or trailing slashes in hardcoded URIs; assuming the wasm build accepts any namespace because the TS type is string.

Understand the failure class

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/b0b0b32c4e35cca9. Report an issue: GitHub.