BabylonJS/Babylon.js · error
att() after start tag closed for <${ctx.name}>
Error message
att() after start tag closed for <${ctx.name}> What it means
XmlBuilder.att() throws this error when the current element's start tag has already been closed (children or text started, or the tag was self-closed). XML attributes must appear inside the start tag, so once ctx.closed is true the attribute cannot be added and the builder refuses to emit invalid XML.
Source
Thrown at packages/dev/serializers/src/3MF/core/xml/xml.builder.ts:138
}
this._w.write(XmlSyntax.Question, XmlSyntax.CloseTag);
return this;
}
/**
*
* @param ns
* @param n
* @param v
* @returns
*/
public att(ns: string | null, n: string, v: string): IXmlBuilder {
const ctx = this._peekContext();
if (!ctx) {
throw new Error("att() without open element");
}
if (ctx.closed) {
throw new Error(`att() after start tag closed for <${ctx.name}>`);
}
// explicit namespace declaration: xmlns or xmlns:prefix
if (this._isXmlnsDecl(ns, n)) {
if (n === XmlSyntax.Xmlns) {
// default namespace
ctx.defaultNs = v;
// you can store default as empty prefix if you want
this._registerNamespace(ctx, "", v);
this._writeAttStr(XmlSyntax.Xmlns, v);
} else {
if (!ns) {
const prefix = n.slice(6); // "xmlns:"
this._registerNamespace(ctx, prefix, v);
this._writeAttStr(n, v);
} else {
this._registerNamespace(ctx, n, v);
this._writeAttStr(`${ns}:${n}`, v);
View on GitHub (pinned to 0592b347b8)
Solutions
- Move all att() calls immediately after the element is opened and before text()/child elements.
- Restructure the code to collect attributes first, then open the element with them.
- Ensure no intermediate text() or child el() call occurs before all attributes are written.
- If using helper wrappers, make sure they do not close the start tag implicitly before attributes are added.
Example fix
// before
b.el("item").text("x").att(null, "id", "1"); // throws
// after
b.el("item").att(null, "id", "1").text("x"); Defensive patterns
Strategy: validation
Validate before calling
function canAddAttribute(b: XmlBuilder): boolean {
const ctx = (b as any)._peekContext?.();
return !!ctx && !ctx.closed;
}
if (canAddAttribute(b)) b.att(ns, name, value); Try / catch
try {
b.att(ns, name, value);
} catch (e) {
if (e instanceof Error && e.message.startsWith('att() after start tag closed')) {
// collect attributes before opening the element and rewrite the section
} else throw e;
} Prevention
- Emit all attributes immediately after opening the element.
- Never interleave text() or child el() before the last att().
- Collect attributes into an object first, then write them in one place.
- Lint/review builder chains for attribute-after-content ordering.
When it happens
Trigger: Calling att() after text(), after a child element was opened, or after the element was closed/self-closed — anything that set ctx.closed before the attribute call.
Common situations: Streaming-style builder code where attributes are appended after content; accumulating attributes in a loop that runs after el()/text(); framework callbacks firing out of order (content written before attribute collection finished).
Related errors
- att() without open element
- text() without open element
- Atmosphere only supports one light source currently.
- Multi-file loading not allowed on env files.
- WebGPUComputeContext.getBindGroups: bindingsMapping is requi
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/30d0180593a2eb21.
Report an issue: GitHub.