BabylonJS/Babylon.js · error

reserved prefix '${prefix}'

Error message

reserved prefix '${prefix}'

What it means

XmlBuilder._registerNamespace() rejects attempts to bind the XML-reserved prefixes 'xml' and 'xmlns' to custom namespaces, per the XML Namespaces spec where these prefixes are predefined and immutable. Registering them would produce invalid namespace declarations, so the builder throws immediately.

Source

Thrown at packages/dev/serializers/src/3MF/core/xml/xml.builder.ts:289

    private _escAttr(s: string): string {
        return this._escText(s).replace(/"/g, """).replace(/'/g, "'");
    }

    private _isXmlnsDecl(ns: string | null, n: string): boolean {
        if (ns) {
            return ns === XmlSyntax.Xmlns;
        }
        const l = n.length;
        const s = XmlSyntax.Xmlns.length;
        if (l >= s) {
            return n.startsWith(XmlSyntax.Xmlns) && (n.length == s || n[s] == XmlSyntax.Semicolon);
        }
        return false;
    }

    private _registerNamespace(ctx: InstanceType<typeof XmlBuilder.Context>, prefix: string, uri: string) {
        if (prefix === XmlSyntax.Xml || prefix === XmlSyntax.Xmlns) {
            throw new Error(`reserved prefix '${prefix}'`);
        }

        const existingUri = ctx.prefix2ns.get(prefix);
        if (existingUri && existingUri !== uri) {
            throw new Error(`prefix '${prefix}' already bound to a different namespace`);
        }

        const existingPrefix = ctx.ns2prefix.get(uri);
        if (!existingPrefix) {
            ctx.ns2prefix.set(uri, prefix);
        }

        ctx.prefix2ns.set(prefix, uri);
    }

    private _allocPrefix(ctx: InstanceType<typeof XmlBuilder.Context>): string {
        let i = 1;
        while (true) {

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Use a non-reserved prefix (anything other than 'xml'/'xmlns') for your namespace URI.
  2. Validate/sanitize user- or config-supplied prefixes before passing them to the builder.
  3. Fix prefix-generation logic to exclude reserved names from candidates.
  4. If you need the standard xml namespace, rely on the implicit predefined binding instead of declaring it.

Example fix

// before
b.att("xmlns", "xml", "http://my.namespace"); // throws
// after
b.att("http://my.namespace", "myattr", "value"); // builder declares e.g. xmlns:ns0=...
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = ['xml', 'xmlns'];
function assertSafePrefix(prefix: string): void {
    if (RESERVED.includes(prefix)) throw new Error(`prefix '${prefix}' is reserved`);
}
assertSafePrefix(myPrefix);

Type guard

function isSafePrefix(p: string): boolean {
    return p !== 'xml' && p !== 'xmlns' && /^[A-Za-z_][\w.-]*$/.test(p);
}

Try / catch

try {
    b.att(ns, n, v);
} catch (e) {
    if (e instanceof Error && e.message.startsWith('reserved prefix')) {
        // swap in a generated non-reserved prefix and retry
    } else throw e;
}

Prevention

When it happens

Trigger: Calling att() with ns/name forming an xmlns:xml or xmlns:xmlns declaration, or _ensurePrefixDeclared() choosing/resolving the reserved prefix for a namespace URI mapping.

Common situations: Hardcoding prefix 'xml' for a custom namespace by mistake; a prefix generator/collision resolver that can pick 'xml' or 'xmlns'; copying a namespace map that includes reserved prefixes; user-supplied prefix configuration without validation.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/88af11e64a753c18. Report an issue: GitHub.