The seven errors every Tableau extension throws
Tableau's extension errors are terse to the point of rudeness. Most of them are one line, several are just a blank rectangle where your extension should be, and one is a hex code. They're also finite. Here are the seven you'll actually hit, what each one really means, and the fix.
First, the thing nobody tells you: errors are step three, not failure. Building an extension is a loop: write it, load it in Tableau, read the error, fix, reload. One or two cycles to clear is normal even when you know what you're doing. If you're pasting an error into an AI assistant, paste the exact text; these messages are terse but they are specific, and the specificity is the only thing that makes them fixable.
01 · My manifest change did nothing
.trex, reloaded, and Tableau is still running the old one..trex once and embeds a copy in the workbook. The file on disk stops mattering..trex directory you used, so it's about four seconds.This one is worth internalising early, because it disguises itself as every other error on this list. You'll fix a genuine manifest bug, see the identical failure, and conclude the fix didn't work, when actually Tableau never read it.
02 · It loads, but it's blank
The deeper fix is to make this error impossible to see. An extension that renders nothing when its inputs are missing is indistinguishable from an extension that's broken: by you, and by every colleague who opens the workbook later. Always render a real empty state:
// Not a blank box, a sentence that says what to do. if (!worksheet || !measures.length) { show('Add a worksheet with a measure to this dashboard'); return; }
Ten seconds of work that converts a support conversation into something the user fixes themselves.
03 · "Missing XML element"
.trex. This is the single most common first-load error, and it's almost always a hand-written or AI-generated manifest that looked complete.default-locale, name, description, author, min-api-version, source-location, icon.Order genuinely matters: the schema is a sequence, not a set. A manifest with every required element in the wrong order fails exactly like one that's missing an element. The full anatomy is here.
04 · It won't load at all, just spins
url is pointing at a port that's now serving something else, or nothing.This one cost me seventy minutes during a live build. There is no error message anywhere in the chain (not in Tableau, not in the terminal) because from Tableau's point of view nothing has gone wrong yet. It's still waiting.
The reliable habit: before debugging anything else, open the manifest's URL in a plain browser tab. If your extension doesn't render there, it will never render in Tableau, and the problem is in your server, not your extension.
05 · Data reads empty when there's clearly data
getSummaryDataAsync returns columns in pill order, which changes every time the user rearranges the sheet.dataType ('float' / 'int') or by name. Use nativeValue for arithmetic. formattedValue is a display string and will quietly poison your maths.// Breaks the moment someone reorders the pills. const total = rows.reduce((a, r) => a + r[2].nativeValue, 0); // Survives it. const m = table.columns.find(c => c.dataType === 'float' || c.dataType === 'int'); const total = rows.reduce((a, r) => a + r[m.index].nativeValue, 0);
06 · FD722608: the content-model error
missing elements in content model '(… source-location,icon,permissions?,…)'<icon> element. Some Tableau builds list it as required (note there's no ? after icon in that content model, while permissions has one), so leaving it out fails to parse, even though plenty of older templates omit it.<icon/> immediately after </source-location>. That's it. No attributes, no content. <source-location>
<url>https://your-host.example.com/index.html</url>
</source-location>
<icon/> <!-- this line. this is the whole fix. -->
</dashboard-extension>
Learning to read that error message is worth more than the fix itself, because the same code
covers a whole family of problems. The parenthesised list is the schema: elements in
required order, a ? marking the optional ones. Whatever's in that list and missing
from your file is your answer.
Building a viz extension? FD722608 has a second, nastier cause there: an
encoding-icon token that isn't in Tableau's enumeration. The published docs list
tokens that the parser rejects, and it reports only the first bad one, so you fix and re-fail
several times over. More on viz extensions here.
07 · Fine on desktop, broken once published
.trex still points at localhost, or the URL isn't on the site's safe list. Desktop is far more permissive than Server: that gap is the whole error.HTTPS, with a real certificate.
Tableau will not load a production extension over plain http, and self-signed
certificates fail too. Everything else on this list is a bug you can argue with. This one
is not negotiable, and real certificates are free.
One related non-bug, because people file it as one: extensions don't render in PDF exports or printed images on Server and Cloud. Blank space where the extension was is expected behavior, not something you can fix in your code.
When to stop fixing and start over
If you're three iterations deep on the same error with no movement, rewriting that piece from a clean prompt is nearly always faster than a fourth patch. State the goal, the field setup, and what's failing, and let it regenerate. Patching a misunderstanding just layers more code on top of it.
Or skip the whole catalog: these seven fixes (and the viz-extension ones) are baked into a free SKILL.md your coding agent reads before it writes a line, so the errors mostly never happen. Emailed to you, free.
The other twenty fixes are in the Kit.
These seven are the dashboard-extension errors. Viz extensions have their own catalog:
the encoding-token enumeration, the hidden attribute that silently loses to your
own CSS, the configure dialog that opens from a gear button because the Marks-card menu
won't fire it, the pane-scaling rules that stop a card looking lost at full-sheet size.
The TableauOps Extension Kit ships that full catalog as a skill file Claude Code reads before it writes a line (so the errors mostly don't happen) plus seventeen working extensions to start from. The Complete Kit adds the whole nine-lesson course for $20 more: $119 instead of $148 bought separately. And when something does break, hosting is the part you can stop thinking about.
You just read seven errors and their fixes. The free skill file bakes all of them (plus the viz-extension catalog) into one SKILL.md your agent reads before it writes a line: get it emailed to you, or leave your email here for the next piece.