Errors & fixes

The Studio check catalog

Every check the TableauOps build engine runs on an extension before it ships: the id, what it means, and the fix.

Eric SummersUpdated 2026-09-18markdown

Studio, the AI builder, and the MCP publish path all run one check engine before an extension ships. Every finding it can raise is listed here, with why it matters and the fix. If you hit a check id, this is the page that explains it.

Component contract

Check What it means Fix
src.empty No source. There is nothing to compile. Write a function Component({ data, schema, theme, fields, config }) that returns markup.
src.component-missing No function named Component. The runtime calls Component by name. Anything else is never invoked and the tile renders nothing. Name the entry function exactly Component. No default export, no arrow assigned to another name.
src.import-export import or export statement. The sandbox has no module loader. React 18 and d3 v7 are the only globals; an import throws at load. Delete every import and export line. Use React and d3 directly as globals.
src.compile Source does not compile. The JSX failed to transform, so nothing can render. Read the compile error, which points at the line, and fix the syntax.
src.viz-line-missing Missing the // viz: metadata line. The build reads the chart type from a // viz: comment. Without it the type is unknown. Add a top-of-file line: // viz: {"type":"bar","variant":"grouped"} with a type from the closed list.
src.viz-line-invalid The // viz: line is not valid JSON. The comment could not be parsed, so the chart type is unreadable. Make the // viz: line a single valid JSON object with a known "type".

Marks-card tiles

Check What it means Fix
fields.none No encodings declared. A viz extension with zero tiles binds to no data and silently renders nothing. This is the most common "blank pane". Declare 1 to 4 tiles on the // fields: line, each with id, name, accepts, and an icon.
fields.too-many More than four tiles. Tableau's schema caps a viz extension at four custom encodings (maxOccurs=4). A fifth is rejected on load. Reduce to four tiles. Fold optional roles into one "any" tile if you must.
fields.entry-invalid A tile entry is malformed. One item on the // fields: line could not be parsed into a tile. Each tile needs id, name, accepts (dimension|measure|date|any), max, and icon.
fields.id-invalid Tile id has illegal characters. Encoding ids must match [a-z0-9_-]; others break the manifest. Rename the tile id to lowercase letters, digits, hyphen, or underscore.
fields.id-case Tile id is not lowercase. Tableau lowercases encoding ids; a mixed-case id will not match at runtime. Make the id all lowercase.
fields.id-duplicate Two tiles share an id. Duplicate ids collide on the Marks card; only one binds. Give every tile a distinct id.
fields.id-reserved Tile id is reserved. "detail" and "tooltip" are Tableau built-ins. A custom tile using one is indistinguishable at runtime. Rename the tile; never use detail or tooltip as a custom encoding id.
fields.id-builtin-name Tile id matches a built-in encoding name. color/size/shape/text/label/angle/path are built-in tile names; reusing one confuses the binding. Choose an id that is not a built-in encoding name.
fields.icon-missing Tile has no icon. Every Marks-card tile needs an . A missing one fails the manifest. Add an icon token to the tile (see the encoding icon tokens reference).
fields.icon-unknown Icon token is not in the schema. Tableau rejects an value outside the 78-token list. Use a token from the encoding icon tokens reference. Note the public docs list line and detail, which the schema rejects.
fields.icon-unverified Icon token is valid but unproven. The token is in the schema but has not been seen rendering in Desktop, so it may not draw. Prefer a verified token, or test the tile in Desktop and confirm the icon shows.
fields.icon-duplicate Two tiles use the same icon. Duplicate icons trigger Tableau error ED626076 and the extension fails to add. Give each tile a distinct icon token.
fields.max-invalid Tile max is not a positive integer. The per-tile field cap must be a whole number of one or more. Set max to a positive integer (how many fields the tile accepts).
fields.accepts-unknown Tile accepts an unknown role. accepts must be dimension, measure, date, or any. Set accepts to one of the four allowed values.
fields.name-generic Tile name is generic. A name like "Field" gives the user no idea what to drop there. Name the tile for the role it plays, e.g. "Category" or "Height".
fields.line-missing Missing the // fields: line. Without a fields line the build cannot know the encodings. Add a // fields: [ ... ] line declaring the tiles.
fields.line-invalid The // fields: line is not valid JSON. The tiles array could not be parsed. Make // fields: a single valid JSON array of tile objects.
fields.declared-unread A declared tile is never read. The component declares an encoding it never uses, so the user drops a field that does nothing. Read the tile via fields/data, or remove it from the // fields: line.
fields.read-undeclared Reading an encoding that is not declared. The component reads a tile id that no // fields: entry declares; it will always be empty. Declare the tile on the // fields: line, or stop reading it.
fields.dynamic-access Encoding accessed dynamically. A computed key into the encodings cannot be statically verified, so the read/declare checks cannot help. Access encodings by literal id so the tooling can verify them.

Sandbox hygiene

Check What it means Fix
code.network Network call in the component. fetch/XHR is blocked in the extension sandbox and Tableau blocks cross-origin calls. Render only from the data Tableau passes in. No network.
code.storage localStorage or sessionStorage use. Web storage is unavailable or partitioned in the embedded browser. Keep state in the settings (Tableau settings API) or in memory.
code.eval eval or Function constructor. Dynamic code evaluation is blocked by the sandbox CSP. Remove eval and new Function; write the logic directly.
code.dom-access Direct document/DOM access. Reaching outside the React root fights React and can break on re-render. Render through React and d3 into the component root, not document globals.
code.parent-window Reaching into window.parent or top. The extension is cross-origin to the host; touching the parent throws. Talk to the host only through the Extensions API.
code.timers Uncleared timer. A setInterval/setTimeout that is never cleared keeps firing after the tile is torn down and can crash Tableau. Clear every timer in a cleanup (return from useEffect).
code.tableau-api Calling the Tableau API from a viz component. A viz extension receives its data as props; calling the dashboard Extensions API is a category error. Read from the data/fields/schema props, not tableau.extensions.
code.d3-select d3.select on a shared selector. Selecting by a non-scoped selector can grab another tile on the same dashboard. Scope d3 selections to the component root element.
code.date-local Local-time date construction. new Date(string) parses in the viewer local zone and buckets shift between users. Bucket dates explicitly (UTC or a chosen zone), not via local Date parsing.
code.no-viewbox SVG without a viewBox. A fixed-size SVG does not scale to the tile and clips or leaves whitespace. Give the root SVG a viewBox and width/height 100%.
code.fixed-size Hard-coded pixel dimensions. The tile is resized by the user; fixed pixels do not follow. Measure the container and render responsively, or use viewBox scaling.
code.no-empty-guard No empty-data guard. Before a field is dropped the data is empty; without a guard the component throws and shows a blank pane. Return a friendly empty state when there are no rows or no required tile is bound.
code.css-var-color Hard-coded color instead of the theme. A literal color ignores the theme token and looks wrong in the other mode. Use the theme prop (palette/accent) so light and dark both work.

Runtime API use

Check What it means Fix
rt.enum-unknown Unknown API enum value. A string passed where the API expects an enum member does not match any value and throws at runtime. Use a value from the Extensions API enums reference.
rt.feature-guard Using an API feature without a version guard. A method added in a later API version throws on older Tableau builds. Guard the call by API version, or raise the manifest min-api-version.

Project metadata

Check What it means Fix
proj.name Project name is empty. The extension needs a human name for the manifest and the splash. Give the project a name.
proj.ext-id Extension id is missing or malformed. The reverse-DNS id identifies the extension to Tableau; a bad one fails the manifest. Use a reverse-DNS id like com.exthost...
proj.version-semver Version is not semver. The manifest version must be X.Y.Z. Set the version to three dot-separated numbers.
proj.dev-url Local dev URL is not localhost http. The local manifest points at a dev server; only http on localhost is allowed there. Point the local manifest at http://localhost:/...
proj.hosted-url Hosted URL is not https. Tableau requires https for a hosted extension source (localhost excepted). Serve the hosted extension over https.

The manifest

Check What it means Fix
trex.xml-malformed Manifest XML does not parse. A malformed .trex cannot be read by Tableau at all. Fix the XML so it is well formed.
trex.root Wrong root element. The manifest root must be . Wrap the document in a single root.
trex.type Wrong or missing manifest type. The manifest declares whether it is a dashboard or viz extension; the wrong type loads the wrong host. Set the manifest type to dashboard-extension or viz-extension as appropriate.
trex.name-empty Empty . Tableau shows the name in the add dialog; empty reads as broken. Fill in the element.
trex.id-pattern Extension id fails the pattern. The must match the reverse-DNS pattern or the manifest is rejected. Use a valid reverse-DNS id.
trex.version-semver Manifest version is not semver. The must be X.Y.Z. Use three dot-separated numbers.
trex.min-api-format min-api-version is not N.N. The minimum API version must look like 1.12. Set min-api-version to a major.minor value.
trex.min-api-viz-floor min-api-version below the viz floor. Viz extensions need at least API 1.12 (Tableau 2024.2). A worksheet default of 1.4 or 1.11 fails to add. Set min-api-version to 1.12 or higher for a viz extension.
trex.child-order Manifest children out of order. Tableau's XSD is order-sensitive; wrong order throws FD722608 (no declaration found). Order the manifest children exactly as the schema requires.
trex.child-missing A required child is missing. The manifest is incomplete and fails validation. Add the missing required element.
trex.child-unknown An unknown child element. An element the schema does not define fails validation. Remove the element that the schema does not allow.
trex.child-duplicate A child element appears too many times. An element repeated past its schema maximum is rejected. Remove the extra occurrence.
trex.comment-double-hyphen Double hyphen inside an XML comment. -- is illegal inside an XML comment and throws FD722608. Remove the -- from the comment text.
trex.encoding-child-order Encoding children out of order. The children of an are order-sensitive too. Order the encoding children as the schema requires.
trex.encoding-count Too many encodings in the manifest. More than four custom encodings is rejected (maxOccurs=4). Reduce to four encodings.
trex.encoding-utf16 Encoding name has non-ASCII bytes. Certain characters in an encoding name break the manifest parse. Use plain ASCII for encoding names.
trex.icon-base64 Icon data is not valid base64 or too large. An embedded icon over the size cap or with bad base64 fails to load. Provide a small, valid base64 PNG (under the size cap), or use an icon token.
trex.icon-empty Empty icon element. An empty renders nothing and can fail validation. Remove the empty icon element or fill it.
trex.author-attrs Author element missing attributes. The needs name and organization/email/website attributes. Fill in the author attributes.
trex.author-website-https Author website is not https. The author website URL must be https. Use an https URL for the author website.
trex.url-count Wrong number of source-location URLs. The manifest expects exactly one under source-location. Provide a single source-location URL.
trex.url-scheme Source URL has the wrong scheme. Hosted needs https; local needs http on localhost. Fix the source-location URL scheme.
trex.permissions-value Unknown permission value. A the schema does not define is rejected. Use a permission value the schema defines (e.g. full data).
trex.context-menu Context-menu element problem. A malformed context-menu block fails validation. Fix or remove the context-menu element.
trex.resources-nested nested wrongly. A misplaced throws "no declaration found for element resources". Place where the schema expects it, or remove it.
trex.resource-ref-missing A referenced resource is missing. The manifest points at a resource that is not declared. Declare the resource or drop the reference.

Manifest-changing edits

Check What it means Fix
diff.tiles-changed The encodings changed since the last save. Changing tiles changes the manifest, so an already-installed copy must be re-added, not reloaded. After a tiles change, remove and re-add the extension in Tableau (a reload keeps the old manifest).
diff.tiles-removed A tile was removed. Removing an encoding is a breaking manifest change for anyone who bound a field to it. Expect installed copies to lose that binding; re-add the extension.