Data Catalog: assets, columns, tags, and documents¶
The Data Catalog is Datahub's registry of every dataset that matters — its name, owner, columns, business terms, tags, and the documents that explain it — and the single source of truth that Metrics, Glossary, Data Products, Contracts, Lineage, and AI all read from.
If your organisation can answer "which tables do we have, who owns them, and what do they mean?", you have a working catalog. This module is how you get there.
When to choose this¶
-
Register any dataset
Make a Databricks table, an ADLS Delta table, an external dashboard, or any other asset visible in Datahub with a name, owner, description, tags, and a governed status lifecycle.
-
Tag and classify your data
PII, GDPR, finance, customer — tags are first-class entities that the Glossary, Metrics, AI, and Contracts modules all consume.
-
Attach documents that explain the data
Upload PDFs, paste markdown, or link a URL. Documents are chunked, embedded, and semantically searched, then surfaced when relevant.
-
:material-vector-search:{ .lg .middle } Find data by meaning
Vector embeddings let you search "tables containing customer email addresses" — even when no column is literally named that.
When not to reach for the Catalog
- You need the row data itself — the Catalog stores metadata, not the data. Connect a warehouse via the Metadata Engine; the rows live there.
- You want to discover schemas from a connection → use the Metadata Engine (it discovers; the Catalog registers).
- You want business terms → use the Business Glossary (a different module, though terms link to assets via term–asset links).
How the catalog fits together¶
However an asset is registered — by hand, by bulk import, or promoted from a Metadata Engine snapshot — it becomes one governed record. Its columns, tags, documents, and lineage all hang off that record, and every other module reads it instead of keeping its own copy.
flowchart LR
M["Manual entry"] --> A
I["Bulk import<br/>CSV / Excel"] --> A
C["Metadata Engine<br/>connection"] --> S["Snapshot"]
S --> P["Promote schemas"]
P --> A
A(["Catalog asset"]) --> COL["Columns<br/>+ PII flags"]
A --> TAG["Tags and domains"]
A --> DOC["Documents<br/>chunked + embedded"]
A --> LIN["Lineage<br/>upstream / downstream"]
A --> CONS["Consumers<br/>Metrics · Glossary · Data Products · Contracts · AI"]
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class A accent
Figure 1 — However an asset gets registered, it becomes the single record other modules read: columns, tags, documents, and lineage all hang off it.
Why teams reach for this
Register a dataset once and every module reuses it: Metrics compute on it, the Glossary binds terms to it, Data Products wrap it for contracts, Lineage traces it, and AI answers questions about it. One source of truth, one governed lifecycle, one place to find data by meaning — no copies to keep in sync.
Domain concepts¶
| Concept | What it is | Notes |
|---|---|---|
| Data Asset | A registered dataset (table, view, dashboard, ML model, external URL). | Has a status lifecycle, owner, tags, columns. |
| Column Definition | A named, typed column on an asset, with optional description and PII flag. | Powers per-column lineage and PII discovery. |
| Tag | A free-form classification (e.g. PII, GDPR, finance). System-managed and tenant-extensible. | Used everywhere — glossary, metrics, alerts. |
| Domain | A bigger-than-a-tag grouping (Finance, HR, Sales). System table. | Most assets belong to one. |
| Document | A PDF, markdown, or URL attached to one or more assets. | AI-chunked + embedded for semantic search. |
| Document Chunk | A semantic chunk of a document (paragraph-sized). | What the AI retrieves when answering questions. |
What the Catalog looks like¶
| Surface | Where | What you see |
|---|---|---|
| Overview | /data-catalog |
KPIs (assets total, drafts in review, published, archived), trend chart of new assets, top tags, recent activity. |
| Assets list | /data-catalog/assets |
Filterable table — name, type (Table / Advanced), owner, status, tags, domain. KPIs at the top. |
| Asset detail — Overview | /data-catalog/assets/{id} |
Description, owner team, type, source, status with state-machine actions, tags, glossary terms attached, audit metadata. |
| Asset detail — Columns | /data-catalog/assets/{id} (Columns tab) |
Per-column metadata: name, type, description, PII flag, lineage. |
| Asset detail — Records | /data-catalog/assets/{id} (Records tab) |
The asset's rows, in the same table as every other list: sort, filter per column, search, page size, plus the version, Added or changed only and violations filters. |
| Asset detail — Documents | /data-catalog/assets/{id} (Documents tab) |
Documents attached to this asset, with previews. |
| Asset detail — Lineage | /data-catalog/assets/{id} (Lineage tab) |
Upstream and downstream dependencies — other assets, metrics, dashboards, contracts. |
| Documents | /data-catalog/documents |
A standalone document library across the catalog — searchable, filterable, with AI-extracted summaries. |
| System tables | /admin/system-tables |
Tags, domains, departments, asset types — the registries the Catalog (and the rest of the platform) draws from. |
The change figures under the KPIs on the Overview, the Assets list and the Documents list count all time until you pick a window in the Period pill above them (1, 7, 14, 30, 90 or 365 days). Clear the pill to go back to all time. The chosen period is kept in the page address, so a shared link opens on the same period.
Finding rows on the Records tab. Sorting, filtering and search cover all of the asset's rows, not only the page on screen. Click a column header to sort by it (ascending, then descending, then off); click another header to sort by it next, up to three columns. Numbers and dates sort as numbers and dates, text ignores case, and empty cells come last. A yes/no column or a column with allowed values filters by a pick list, and so does a text or number column with fewer than 100 different values (never a key column). A number column with 100 or more different values filters by a range instead: fill in From, To or both (both are included, and a decimal takes a point, as in 3.5). The pill then reads 10 – 200, ≥ 10 or ≤ 200, and its × clears it. A record whose value in that column isn't a number, or is empty, never matches a range. A date filters by a range too. For text with more values, use the search box. A column a formula calculates can't be sorted or filtered by. Select all matching selects every row the search and filters match, and Export, a bulk edit or a bulk delete then covers exactly those rows. Violations only works the same way: it lists every row of the version shown that has a violation, however many there are, and select all matching, export and bulk edits cover those rows. With no rows ticked, Export N matching exports every row the list matches, in the list's order; with rows ticked, Export selected exports just those rows. Changing the search, a filter, the version, Changed only or Violations only unticks every row, since the rows you ticked may no longer be listed (so does Violations only switching itself off once the last violation is fixed); sorting, paging or changing the page size keeps them ticked. When nothing matches, the table says so and offers Clear filters.
Finding archived rows. The N archived button above the records opens the rows archived from the asset, from every version, the most recently archived first. It sorts, filters and searches like the Records tab, across all archived rows, with the same page sizes and Clear all. A text or number column filters by "contains" here: there is no pick list of its values and no number range, so use the search or that filter. Each time you open it, it starts without a sort or filter. An editor can restore one row, the ticked rows (with Restore in the selection bar), or every row when they all fit on one page. Under a search or filter that button reads Restore matching and restores only the rows the filter shows. When the rows don't all fit on one page, the button is disabled, and hovering it says how to get them onto one page: show more rows per page, or narrow the search or filters. A selection covers only the rows on screen: when a sort, search, filter or page change takes a ticked row off the screen, it is no longer selected.
Setup — what an admin does once¶
| Prereq | Where | Why |
|---|---|---|
| Tags & domains seeded | /admin/system-tables |
The platform ships sensible defaults; tenants typically add 5–20 of their own. |
| Owner teams | /admin/teams |
Every asset has an owner team. |
| Roles | /rolegroups |
datacatalog.assets.read, datacatalog.assets.write, datacatalog.assets.approve. |
| AI provider (optional) | /admin/integrations → AI Provider Keys |
Required for AI-enhanced document processing (chunking, summarisation, embeddings). |
| Metadata Engine connection (optional) | /admin/integrations → Metadata Engine |
If you want bulk import from a warehouse, connect it. |
| Advanced assets (optional) | /admin/governance → Advanced assets |
Off by default — turn on before anyone in the organisation can create or upgrade an asset to advanced. Every advanced asset re-queries its connected warehouse on every view, so this is a deliberate cost/governance decision, not just a feature flag. Turning it off later never strands an asset that's already advanced — it keeps working and stays editable. |
Registering an asset¶
Three on-ramps, and whichever you take the new asset starts in draft status.
/data-catalog/assets → New asset → name, type, source, description, owner, tags, columns. Best for one-off registrations.
Choose a CSV or Excel file and its rows come with the new table: the window previews them, then imports on Confirm import. A large file imports in the background, and the window shows how long it has run. Once the first rows are processed, its bar fills and a line says how many of the file's rows are done so far, with a percentage. It waits for the import up to ten minutes, or until you choose Continue in background. Then the new table opens with its columns in place while its rows are still arriving. You can close the tab: the import runs on. When it ends, the Notifications bell tells you how: how many rows were imported, or why the import failed. The entry opens the table's Records tab. Only you, the person who started the import, get it, and it stays in the bell for a week. While the tab is still open, a short notice also pops up as the import ends.
Import on /data-catalog/assets → upload a CSV or Excel file (up to 25 MB). The platform previews rows, validates them, optionally enriches with AI (suggested descriptions, tags, owners), and lets you confirm row by row before commit. The preview names each new, changed and deleted record by its first identifying values (for example name: Alice · city: Delft) and by its row in your file, counted from the first row under the header. A changed record lists its first changed columns in the table, and clicking the record shows every change. An empty value reads (empty). Large files import in the background. When you import into an existing table with Import data on its page, the window stays open while they do: once the first rows are processed, its bar fills and a line says how many of the file's rows are done so far. When the import finishes, the window closes and the Records tab shows the rows; if it fails, the window stays open and says why. It waits up to ten minutes, or until you choose Continue in background: the import then runs on, and a notice says when it has finished while Datahub stays open in that tab. Whether that tab stays open or not, when a background import ends the Notifications bell tells the person who started it how it ended, and why if it failed; the entry opens the asset's Records tab. Each import appears in the asset's history with the file name, how many rows it added and updated, and who ran it. Only a row the file changes counts as updated. Any other row is left as it is and gets no history entry. An empty cell keeps the stored value, and an advanced asset's remote columns are never written. Importing an asset's own export therefore updates nothing, and the preview's "modified" count is the number the import reports. A bulk update from a file also records how many rows it archived, and each archived row names the file. For datasets beyond that, connect a Metadata Engine source and promote from a warehouse snapshot instead of moving the rows through a file.
Connect a warehouse via the Metadata Engine, take a snapshot, then Promote selected schemas to catalog assets. The catalog row keeps a back-pointer to the snapshot, so column changes show up automatically on the next snapshot.
The asset lifecycle¶
Every asset moves through the same governed states as the rest of the platform: a human reviewer consciously approves an asset before it becomes the published source of truth, and nothing is hard-deleted without first being archived.
stateDiagram-v2
direction LR
[*] --> Draft: Register
Draft --> UnderReview: Submit for review
UnderReview --> Draft: Reject / withdraw
UnderReview --> Published: Reviewer approves
Published --> Archived: Archive
Archived --> Published: Restore
Archived --> [*]: Permanent delete
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class Published accent
Figure 2 — Every asset starts as a draft and only becomes the published source of truth after reviewer approval. Archiving is a reversible soft delete; permanent delete is allowed only from Archived and warns about every dependent metric, contract, product, and glossary link.
| Status | Meaning | Who can move it |
|---|---|---|
| Draft | Author is iterating; not yet visible to consumers in default lists. | The author or anyone with datacatalog.assets.write. |
| Under review | Submitted for approval; reviewers see it in their Tasks inbox. When nobody in the domain or on the fallback role may approve it, the submitter chooses a reviewing group (never a single person) and the task goes to that group's team inbox. | Triggered by Submit for review. |
| Published | Source of truth; visible to everyone with read access; can be wrapped in Data Products and linked to contracts. | Reviewer approval (datacatalog.assets.approve). |
| Archived | Soft-deleted. Hidden from default lists. Existing references show archived state. | datacatalog.assets.write (with confirmation). |
Permanent delete is allowed only on archived assets, requires confirmation, and warns about every dependent metric / contract / product / glossary link.
A review schedule sends one review reminder each period. A review schedule needs a team: when the next review date arrives, a review task is created for that team, and the date moves on by the interval. The task goes to the first of these who can sign in: the asset's owner (when the owner is a Datahub user rather than a name or an e-mail address), the team's lead, and then the team's other members, longest-standing first. When none of them can, the task is created for the team with nobody holding it, and the catalog editors are told (see Who is told below). You can also name a role group, but it is optional and receives no reminder. A schedule saved earlier with only a role group sends no reminder. The asset page says so, and offers its editors Add a team. If a reminder fails, or someone cancels it in the Operations console, Datahub queues it again within the hour for the review date the asset shows, so a reminder that is already due still goes out. To stop the reminders, remove the review schedule. The Operations console tells you this before you confirm the cancel, and again in the message after it, and its confirm links to the asset. An archived asset gets none, and after Revert to Draft they start again within the hour. Setting or removing a schedule is a change to the asset: someone outside the domain an asset is filed in is refused, as they are for any other edit.
Who is told
Catalog editors don't need to open each asset to find a failed import or a review nobody will see. Every 15 minutes Datahub counts the assets whose latest import failed in the past week, and the scheduled reviews whose reminder has nobody to go to. The Administration page shows both among the checks that need attention. For reviews with nobody to remind, everyone who holds datacatalog.assets.write gets one bell notification that opens the assets list. A failed import is told once, by the import itself: to the person who started it, or, for an import nobody started (one queued before Datahub recorded who started an import), to everyone who holds datacatalog.assets.write. The count adds no second notification. That notification leaves the bell after a week, whether or not the import was run again, so someone who becomes a catalog editor later finds the failure only on the Administration page. When nobody holds datacatalog.assets.write, the people in the Administrator organisation role are told instead, or, when there are none, those in the Administrator role group. A review notification leaves the bell once every scheduled review has someone to remind, for example after you choose a team with a member who can sign in. A review task already created with nobody holding it stays that way: a tasks administrator can reassign it on the Administration tab of Tasks, and the next reminder goes to the new team. A failed import stops counting once a later import into the asset completes, or after a week.
When versioning is enabled¶
Every new asset is versioned. A new table, document or advanced asset is under version control from the moment it is created, whatever Auto-enable versioning says in the admin defaults. Its first version, v1, is a draft: you can import and edit its records straight away, and its author, editors and approvers see them. Someone who can only read the catalog sees Not published yet, and so does anything that reads on nobody's behalf (a flow, a connected AI agent's read tools, an export). Approving v1 makes its records readable and publishes the asset. Turning versioning on for an existing asset works the same way, unless the asset is already published: then its records stay readable as an active v1, and your next change goes into a new draft. You can still turn versioning off for an asset. Turning it back on afterwards works only while the asset's one version is that first draft.
A new asset is published through its own review. Until it has been published once, a table or a document shows the same Submit for Review as any other asset, and that review covers its first version. Approving it publishes the asset and makes v1 its active version, in one step. Rejecting it, or withdrawing it, leaves v1 a draft you can keep working on. While that review is open, v1 can't be submitted on its own or applied directly. An advanced asset is the exception: its first version is reviewed through its own version review, which carries its joins and rules, so its page offers that instead.
From v2 on, each version is reviewed on its own. Once the asset is published, your next change goes into a new draft version, and Submit Draft for Review sends that version to review. Anyone who can edit the asset can submit it. A version review, including an advanced asset's first, is routed the way the asset's own review is: to a steward of the asset's domain, otherwise to a Data Owner who can approve catalog assets. When neither exists, you choose the group that reviews it, from the groups with a member other than you who can approve. Approving it makes it the active version; rejecting it returns it to draft. Documents work the same way as tables here.
Assets with versioning turned on keep their published status tied to an active version (a governed, approved snapshot of the schema). The two states move together:
- Activating a version publishes the asset. When a new version becomes active, a draft asset is reconciled to Published automatically — you don't publish it separately. An asset that is still Under review is left untouched: activation never skips the reviewer.
- You can't publish a versioned asset without an active version. Publishing is blocked until at least one version has been activated, so a versioned asset is never "published" with nothing behind it — nor active with no published parent.
- The Records tab opens on the draft. If the asset has a draft and you may see it (you started it, or you can edit or approve catalog assets), the Records tab shows the draft rather than the published version, so a file you just imported into it is there straight away. After an import the tab returns to the draft, even if you had picked another version. Someone who can only read the catalog keeps seeing the published version. You can still pick any version you may see from the version menu. A version under review does not replace the published one as the default.
- What a draft changed. On a draft, or a version under review, the Records tab marks every row the version added (Added) and every row it changed (Modified, with the number of cells). A changed cell shows its earlier value under the new one ("Was: …"), with who changed it or which rule did. The marks are icons with names, so they can be told apart without colour. The line above the rows counts the whole version against the version it came from, for example "Changes since v2 · 3 added · 7 modified · 1 removed", and a button such as Show the 2 removed rows lists the rows the version removed, struck through. The first version of an asset has nothing to compare with, and says so.
- A draft nobody works on is archived after a while. Your administrator sets the number of days under Draft lifecycle. The count starts at the draft's last change, not when it was created. Changing its records, schema, joins or rules, or its document's content, starts it again, and so do a rebase, a withdrawal from review, a rejected review, and work on a governed query one of its joins uses (an edit to the query, or the query's own review). Editing the asset's own details (name, description, owner) or a document's analysis does not restart it. A dataset's unpublished first version is never archived this way.
- You can discard a draft. While you can edit the asset, Discard draft is in the version's row menu on the Versions tab and in the page's ⋯ menu. Discarding a draft of a published asset archives just the draft, the state an untouched draft reaches on its own (above). The active version is untouched, and you can start a new draft from it. If nothing was ever published, the draft is the asset's first version, so discarding it archives the asset instead. That needs the catalog's approve permission, and restoring the asset brings the draft back. Editors share one draft, so the confirmation names everyone else whose work goes with it, and counts anyone whose account has since been removed. A draft that is under review is withdrawn first.
- An archived asset's draft waits for a restore. While an asset is archived, including by discarding its first draft, its draft can't be submitted, activated or discarded again. Restore the asset first.
- The totals count live assets. The catalog's total assets and total records count assets that are not archived. An archived asset and its rows count again after Revert to Draft.
- An archived asset is read-only. Its page offers no edit control: no columns, records, details, tags, links, joins or rules, and no new version. The platform refuses those changes too. A note in the page header says the asset is archived and who can bring it back. Someone with the catalog's approve permission restores it with Revert to Draft, which makes it an editable draft again. If one of its versions is still under review, that review is rejected or withdrawn first. It gets no review reminders while it is archived, and its editors can still remove its review schedule.
- Unsaved joins or rules hold an advanced draft's Submit. Submit sends the saved draft only. While the save bar on the Advanced tab is up, Submit is greyed out and says why. Save or discard the changes in that bar first.
Non-versioned assets (created before every new asset was versioned, or with versioning turned off) are unaffected — they follow the plain Draft → Review → Published → Archived flow above.
Advanced assets¶
An advanced asset is a table asset that joins its own stored rows with one or more live queries against a connected warehouse (Databricks, Fabric, Azure SQL, or PostgreSQL), then applies an ordered set of rules to derive values for its own columns — including columns that exist only because a rule computes them. It appears in the standard /data-catalog/assets list alongside plain table assets, tagged with an Advanced type badge — open one from there, or from its detail page's Live table link. To see only the advanced ones, filter the list on Type = Advanced, or open /data-catalog/assets?type=advanced (the Advanced assets admin card links there).
Becoming advanced. Once an admin has turned the capability on (see Setup), there are two on-ramps:
- At creation time — New asset offers a Table vs Advanced choice alongside its usual fields. Picking Advanced then asks where the asset starts from:
- A file or an empty table — import a CSV or Excel file now (the same import a table gets), or add rows later.
- A governed query — the query's rows become the asset's rows. Pick the query (only queries with an approved, active version are offered), tick Key on the column (or columns) that identify a row, and choose which other columns to bring in. The key is stored on each row; every other chosen column stays live from the query. The key has to identify one row each: if the query returns the same key twice, the asset is not created and you are asked to choose a different key.
- On an existing table asset — its detail page offers an Upgrade to advanced action, which asks you to confirm first and spells out what changes. The asset's existing data and columns are kept as-is; upgrading only adds the remote join and rule configuration on top.
Either way you end up in the same place: the asset's own Advanced config tab, alongside Schema, Records and the rest. That's where you join governed queries onto the asset's rows, choose the columns each one brings in, and define the ordered rules that derive — or add — column values.
The tab has six subpages, one shown at a time: Live table (the joined table itself: its rows and the draft's pending changes), Remote joins, Columns, Rules, Export targets and Databricks view (see Publish to Databricks below). An editor of a draft that has no join yet starts on Remote joins, since there is no table to see before one exists; everyone else starts on the Live table. Unsaved configuration stays put when you switch subpages, and the save bar stays at the bottom until you save or discard it. Each subpage has its own address, so a link can open any of them: /data-catalog/<asset>?tab=advanced&step=live (or joins, columns, rules, exports, databricks-view). Add &version=<id> to open the tab on one version: every subpage then shows that version, so a reviewer who follows a task's link sees the joins and rules behind the table they review. A version you may not see reads "Not published yet". The live table used to be a page of its own; its old address, /data-catalog/<asset>/advanced-view, now opens the Live table subpage.
A new advanced asset starts as a draft. It is versioned from the moment it is created, and its first version, v1, is a draft: nothing about it has been reviewed yet, and all of its configuration can be edited straight away. Until v1 is approved the asset is not published. Its author, and everyone who can edit or approve catalog assets, see the draft: the Records tab and the Live table open on it, and the version menu names it (for example "v1 (Draft)"). Its author and editors can edit its rows, sync them and submit it; an approver sees it read-only, to review it. Someone who can only read the catalog sees "Not published yet" and who started the draft, and an export or a storage sync refuses rather than hand out unapproved rows. A reader who asks for an unpublished version by name (a comparison, or a direct link) is told it is not published yet instead of shown its rows. Versions that were published once stay readable. It becomes published the ordinary way, when v1 is submitted and approved (or applied directly, if your organisation allows that). Upgrading a table that already has rows works differently: those rows are in use, so they stay readable as a published v1 — whatever the table's catalog status — and your changes go into a new draft.
Several joins. An asset can join more than one query — say, a CRM query for account details and a finance query for revenue. Joins run in order, so a later join can match on a column an earlier join brought in, not only on the asset's own columns. Each join brings in its own columns: when two queries both return a column with the same name, the second one gets the join's name in front (you can rename it before adding). A version shows only the columns its own joins bring in, so a column you add in a draft does not appear on the published version until the draft is approved. Removing a join removes the columns it brought in from the draft; if a rule or a later join still uses one of them, the removal is refused and says which rule or join to change first. If one join's query fails, the message names the join — for example "Join 2 (Customer CRM): …" — and a reader who has no access to one join's warehouse connection is told so. A join can use a query that has no approved version yet only if the query is yours: a draft previews its joins' unapproved SQL, and running someone else's is theirs to allow. The query picker offers your own such queries while they are still a draft, marked Your draft: you can discover their columns and preview the join, and until the query is approved nobody else can, except the approvers while the asset is in review (below). A query you already submitted for review is not offered until it is approved: there is no draft left to preview. The asset cannot go live on such a query before it is approved. Submitting the asset for review sends the query along in the same review. If your organisation approves advanced assets automatically, the submission is refused, naming the join, until the query is approved or activated (as is activating the version directly, where review is turned off). While the asset and its query are in review together, the preview shows the query's rows to you and to anyone holding the catalog approve role, so a reviewer sees the joined data they are approving.
Private queries. A query you create on the Saved Queries pages (or through Create a governed query) is private until you share it, and only its owner can run a private query; one promoted from a join's raw SQL is shared from the start. An asset joined to one could be read by nobody but you, so it cannot be submitted (or applied) until the query is shared: the refusal names the join. The query picker marks your private queries, and the join card offers Share with the organisation (it needs the query-manage role, and asks first: everyone in the organisation can then see and use the query, and it cannot be made private again). The Saved Queries pages offer the same move, so you don't need a join to reach it: Share with organization is in a private query's row menu on the list, and on the query's own page in its Visibility slot and the header's More actions menu. A query filed in a domain you no longer work in can't be shared, and the menu and the slot say why. Anyone else who opens such an asset, a colleague or a steward, is told on the join that its query is private and who owns it (the query's own name only if they may see the query anyway: a steward of its domain, or any steward while it is not filed in one, and holding the query-manage role), and that only the owner can share it. They can still change that join's keys and the asset's rules. Pointing a join at a private query of someone else is refused.
Moves on a saved query. When your organisation requires review, a saved query's draft is not offered Activate: it goes live through review, and the query's page says so. If a query is yours but you lack the permission to manage saved queries, its page says that Share, Submit for review, Activate and Withdraw are not offered because of it, and to ask an administrator for the permission.
Rows from a query. When the asset started from a governed query, that join is marked Rows come from this query. Its key columns identify each row, so they can't be edited — by hand or by a rule. When the query starts returning keys the asset doesn't have yet, Sync rows (on a draft, by anyone who can edit it) adds a row for each of them; rows are only ever added, never removed, so a row whose key disappeared from the query stays, marked as unmatched. Sync rows uses the join's saved query, so it waits until the join has no unsaved changes, and afterwards it says what it did: rows added, rows it skipped because their key was empty, keys the query repeated, and whether the query stopped at its row limit (then narrow or split the query — syncing again would see the same rows). When the draft is submitted, the confirmation lists the rows it adds or removes alongside the changed cells, and the reviewer sees the same.
Rules that add columns. A rule's then set can target + New column…: name it and pick a type, and the column is created when you save. A rule can also compute its value with a formula instead of copying a fixed value or another column, for example round(float(amount) * 1.21, 2) or 'high' if score > 80 else 'low'. Formulas use the same small, sandboxed syntax as computed columns; a formula that names a column the asset doesn't have is refused when you save, not left to produce an empty column. You don't have to type column names: Insert column beside the formula lists the columns you can use and puts the one you pick where your cursor is, spelled the way the formula reads it (a column whose name has spaces or symbols goes in as row["Order Date"]). On an asset with many columns, Insert column has a search field: type part of a name to narrow the list. A long column name wraps instead of running past the menu's edge. Values that come from a warehouse can arrive as text, so wrap them in float() before doing arithmetic.
A rule's value takes its column's type. Whatever a rule copies, fixes or computes is stored the way its column is typed: a number copied into a text column is stored as text (5, not 5.0), a whole number going into an integer column is stored as one, the text yes a rule sets in a true/false column is stored as true, and a date and time copied into a date column keeps the date. A value that can't be converted, such as text going into a number column, is stored as it is and counts as a data violation on the Records tab; the violation names the rule, since only the rule (or the column's type) can fix it. Within one pass a later rule reads an earlier rule's result as it was computed, so cost_b - cost_a works even when both columns are text. A new column starts with a type that fits its rule: decimal for a formula, the copied column's type when the rule copies a column, and text for a fixed value. Once you pick a different type, it stays when you change what the rule sets. Check the type before you save: a formula that returns text, such as 'high' if score > 80 else 'low', needs a text column, and a column that holds numbers needs a number type (decimal or integer), so it is stored, sorted and filtered as numbers.
Rules that build on each other. Rules run from top to bottom over each row, so a rule can use what the rules above it set, including a new column an earlier rule creates before you have saved it. A later rule can also set such a column: its then set list offers it after the asset's columns, marked New column, created by rule N, so several rules can fill one new column. If you rename or remove the rule that creates it, every rule still setting the old name says so on its row straight away. The save is then refused, naming the rule and the column, until you give the column its name back or pick another one. Insert column lists those new columns first, under the rule that sets them, and marks a column that this rule or a later one fills. For example, two rules compute cost_a and cost_b, and a third sets margin to cost_b - cost_a. Keep that third rule below the other two: moved above them, it reads their columns before they are filled, so margin comes out empty or from older values. The builder warns you as soon as that happens: the rule names each column it reads too early and the rule below that sets it, and tells you which rule to move it under. It warns the same way when the only rule that sets such a column is switched off. Reading an existing column before a later rule changes it can be what you mean, for example to keep the original value next to a cleaned one, so when that later rule changes only some rows, or works out the new value from the old one, the rule gets a short note instead of a warning. Once saved, every active rule's column and its results appear in the live preview; until then the preview says it does not show your unsaved changes yet. When a rule stops setting a cell, the cell goes back to the value it had before a rule set it, and the rules below it are worked out again from that value. This happens whether you switch the rule off, delete it, point it at another column, or the row stops matching its condition. In the example, switch off the rule that sets cost_a and cost_a shows its earlier value again, with margin following it. A value someone typed into a cell is never put back, and the submit overview never credits a change to a rule that is off. A published version keeps the values it was approved with.
Grouping conditions with and / or. A rule's If reads as a sentence: its conditions are joined by and (all must hold) or or (one is enough), and you switch the word between them in place. Add group brackets conditions with a word of their own, so one rule can say tier is A and (region is EU or region is UK). A new group starts with the other word, since a bracket usually turns the sentence around. Groups go at most two levels deep inside the If; a deeper one is refused when you save. An empty group is left out until you fill it in. Rules saved before groups existed read exactly as they did: their conditions joined by and, or by or.
Steps: IF / ELSE IF / ELSE. A rule can become a step that decides one column from several cases, tried from the top: the first case that matches sets the column, and the rest are skipped. Choose Add ELSE IF under a rule to add a case, and Add ELSE for the value when none of them match. A step has one ELSE at most, always last and without a condition. Without an ELSE, a row that matches no case keeps the value it had. Every case of a step sets the same column and is switched on or off together; you set both on its first case. Use the arrows on the step to move it, and the arrows on a case to reorder the cases. A later rule or step reads the value a step set, for example a discount step that reads the tier an earlier step decided:
| Step | Cases |
|---|---|
| tier | IF revenue > 1,000,000 → "A"; ELSE IF revenue > credit_limit → "B"; ELSE → "C" |
| discount | IF tier = "A" and (region = "EU" or region = "UK") → 0.10; ELSE → 0 |
Comparing two columns. A condition can compare a column with another column of the same row instead of with a value: switch its right-hand side from Value to Column and pick one, for example revenue is greater than credit_limit. That works with equals, does not equal and the greater than and less than choices; is one of, is not one of and contains compare with a list or with text, so they keep a value. The picker lists what the rules above set first, so a rule can compare with an earlier rule's result. A new column that only a later or a switched-off rule fills has no value yet when the rule runs, so it is not offered, and a save that compares with one is refused. If you move, switch off or delete the rule that sets a column a condition compares with, the condition says so right away, so you can move the rule back or pick another column. A column can't be compared with itself, since that gives the same answer for every row. When either column is empty in a row, the condition does not match that row.
Fix violations before submitting or adding logic. While a draft's rows break its schema, which is the violations count on the Records tab, the draft can't be submitted for review or activated, and you can't add logic: no new rule, no rule switched on, no rule pointed at another column. Submit, Add rule and Save say why and link to the rows (Show violations). You can still change a rule's condition or value, switch a rule off or remove it, because that is often how the violations get fixed. A plain table is not affected: it keeps accepting rows with violations.
Columns a rule calculates are locked. A column an active rule sets holds the rule's values, so nobody types into it: a typed value would make the calculation wrong. It is read-only in the live table, and on the Records tab in the edit popup, the add row and bulk edit, each naming the rule that calculates it; an import whose file carries the column is refused with the same explanation (leave the column out of the file, the rule fills it in). This holds for every row of the column, including rows the rule's condition doesn't match today. To change the values, change the rule; switch the rule off and the column is an ordinary, editable column again. A cell you edited by hand before this lock existed shows the rule's value again the next time the draft's table opens; until then you can still revert it to its original value.
Records and schema of an advanced asset. The Records tab lists the columns stored with the rows; columns filled live from a query are not stored there, so the tab leaves them out and links to the Live table, where their values are. A key column of the query the rows come from can't be changed on the Records tab either. The number of data violations above the rows is for the version the tab shows, and it is counted again after the live table stores the rules' values. On a draft, a value you change on the Records tab (in a row, inline, in a bulk edit or by reverting to an earlier version of the row from its History) is one of the draft's changes, exactly like a change in the live table: the submit overview lists it, with who made it. The Records tab marks the changed cell with its original value and who changed it, and both the Records tab and the live table have a revert control for it. Setting the value back to its original anywhere undoes the change. On the Schema tab, a column that a join or a rule uses by name can't be renamed — the refusal says which join or rule, so you can change that first.
Saving. Changes to joins, rules and the Databricks view link are saved together from the bar that appears at the bottom of the screen as soon as something is unsaved — Save changes or Discard. Joins are saved first, then rules, then the view link (a rule can calculate a column the view's base table lacks), and saving stops at the first refusal: the join, rule or link that refused says why, where it is. Three actions do not wait for the bar and cannot be discarded: Add columns (which saves its join first if needed), Sync rows and removing a join. The live preview and the column list keep a fixed height and scroll inside, so a wide or long asset never pushes the rest of the page out of reach.
Starting from raw SQL. You don't need a governed query to exist first. The join step offers a Write raw SQL mode for the case where nothing suitable is saved yet. That SQL is stored but never run — there is no preview and no column discovery against it, and the version can't be submitted for review (or activated, if your organisation has review turned off) until you promote it. Promoting asks for a name and a warehouse connection, then creates an ordinary governed query from that SQL: owned by you, shared with your organisation, and subject to exactly the same review rules as any query created from the Saved Queries page. The join then switches back to pointing at that query.
Making the query without losing your place. When a join has no governed query to point at, Create a governed query (or Open saved queries, or Open this query on one that still needs activating) takes you to the query pages in the same tab, and a bar under the header says you're on a side task for this asset. Anything else unsaved on the asset is saved to its draft first (you're asked), and the keys you already typed on that join travel with you. Create or activate the query, then Return: the join you came from gets the query — selected and ready for its columns if it can run or is still your own draft, or named with a way to open it otherwise. If someone changed that join while you were away, nothing is applied until you choose Apply mine anyway.
One thing to expect: a newly promoted query starts as a draft with no active version. As its owner you can discover its columns and preview the join straight away, but nobody else can, and the asset cannot go live on it until the query is activated — or approved, if your organisation reviews queries (a review of the asset includes it). The builder says so. Promoting also needs the query-manage role on top of asset-write; without it you can still write and save the SQL, and the screen tells you to ask a steward who has that role.
The configuration lives on a draft version of the asset. Upgrading a table turns versioning on as part of the upgrade; when the asset has a published version and no draft, the tab has a button to start a draft there and then. While a draft is waiting for review, the tab shows the configuration read-only rather than hiding it. A rule's fixed value, and the value a condition compares with, show in full there, in a read-only field you can select and copy.
flowchart LR
A["Admin turns on Advanced assets"] --> B{"Creating or editing a table asset"}
B -->|"Create"| C["Choose Advanced: start from a file or a governed query"]
B -->|"Existing table"| D["Upgrade to advanced, confirm the change"]
C --> E["Advanced config tab: live table, joins, columns, rules"]
D --> E
E --> F{"Is there a governed query to point at?"}
F -->|"Yes"| G["Pick it"]
F -->|"No"| H["Write raw SQL — saved, never run"]
H -->|"Promote: name + connection"| I["An ordinary governed query, awaiting activation"]
I --> G
classDef accent fill:#ff8400,stroke:#e67700,color:#fff
class A accent
- Locked columns (marked with a lock icon) come from the remote query. They're read-only everywhere in the table — there's no way to type into one, not just a greyed-out field.
- Editable columns are your own stored data. Click into a cell to change it.
- Calculated columns are locked too: every cell of a column an active rule sets shows the rule's value, with a lock, and hovering it names the rule. Change the rule to change them (see Columns a rule calculates are locked above).
- On a version that is not published yet, the table marks what the version changed, the same way the Records tab does (see What a draft changed above): new rows, changed rows and each changed cell's earlier value, with who changed it or which rule did. A cell changed by hand, here or on the Records tab, also has a revert control; a value a rule set changes only with the rule. The submit overview says who made each hand-made change.
The table is live, not cached
Every time you open or refresh this view, the platform re-runs the query against your warehouse — it's never a stale snapshot. That also means it can take a few seconds to load on a large or slow source. Editing a cell does not re-run the query for you automatically (that would mean a live warehouse round-trip on every keystroke); use Refresh to re-check the remote data and re-apply rules against it, or trust that either happens the moment you submit.
When the warehouse is starting
The joins run on a SQL warehouse, and a Databricks warehouse that stopped after a quiet period takes a few minutes to start again. The asset's header shows its state in the Warehouse slot: Online, Starting up, Offline or Unknown. Hover it to see why a state is unknown and, when the joins use several warehouses, the state of each one. While a warehouse starts, the live table, the preview on the Advanced config tab and the pending-changes indicator say they are waiting for it, and the rows load by themselves once it is running. A stopped warehouse starts when the joins run, so opening the table is enough to wake it.
Find, arrange and export rows. The table has the same tools as the Records tab. Search looks through every column. Filter narrows the rows per column (a pick-list for a column with a few values, otherwise Contains…; the row key is always Contains…) and on the row itself: With changes pending or No remote match. Table options holds the columns (show, hide, order, pin and size them) and the table's saved views, if it has any. Export CSV downloads the rows that match your search and filters, with the columns you show, in their order, with the values as the table shows them. On a version that is not published yet, the line above the rows counts the rows it added, changed and removed, and can show the removed rows.
When you're done editing, the "N changes pending" count above the table tells you what is waiting. Submit Draft for Review in the asset's header opens a full old-vs-new review — grouped by row, showing which changes were rule-derived versus manual — before anything is actually applied. Depending on your organisation's policy (set by an admin in /admin/workflows), submitting either applies your changes immediately or sends them for review first; the confirmation screen and the result both tell you which.
Publish to Databricks¶
An advanced asset built on a Databricks table can be published as a view in Databricks, so tools that read Databricks see the asset as it is in Datahub. The view holds the asset's logic, not a copy of its rows:
- its joins;
- its rules, including formulas;
- its manual edits, as values the view puts over the base table's own.
It reads the base table each time it is queried. The Databricks view subpage shows where the view stands and, on a draft, is where you link it.
When it publishes. Each time a version of the asset becomes active (approved through the workflow, auto-approved, or activated directly), Datahub publishes that version's view in the background, replacing the one before it. The view keeps the same name. Nothing happens for a version without a view link, or whose link has Publish the view when this version is approved switched off. While view publishing is off for the connection, a linked draft can't be submitted; if it's turned off after a version is active, that version's next publish fails and the status card says so.
What stops a submit. Some logic has no faithful Databricks equivalent. A draft whose view can't be built can't be submitted, and the Databricks view subpage lists each reason with the join, step or column it comes from. Examples:
- a join on a query that runs on another warehouse or workspace;
- a formula using
%,in, slicing or a bitwise operator; - an edited key column;
- a column the base table doesn't have;
- view publishing off for the connection, or no target schema set on it;
- a base table or key columns the metadata harvest hasn't read.
Data violations stop a submit as well, view or no view (see Fix violations before submitting above). A reviewer sees the same reasons, and the exact view SQL, before deciding. Under Good to know, the subpage also lists where the view will differ from Datahub without stopping the submit:
- records added in Datahub have no row in the base table, so the view leaves them out;
- records removed in Datahub still show in the view, because they are still in the base table;
- a few formula edge cases come out differently, such as numbers past the BIGINT range.
Linking it, on a draft. Pick a Databricks connection, the base table the view reads (the tables the metadata harvest has read, grouped by catalog and schema), the column or columns that identify a row in that table, and the view's name. The page shows the full name the view publishes as, <catalog>.<schema>.<view>; an integrations admin sets the catalog and schema per connection. Before you save, it lists the asset's columns the base table doesn't have: pick another table, or have a rule calculate the column. When view publishing is off for the connection, the page says so, and that an integrations admin turns it on in the connection's View publishing tab. Giving the view a new name leaves the old view standing in Databricks: Datahub never drops a view on its own. A link saved on a connection you can no longer use stays in the picker as A connection you can't use. Ask an integrations admin to share it with you, or pick another connection, which starts the table and key columns over.
Its status, on every version. A card shows the view, the version it shows and when it was published, the approval that published it, and who asked for the last publish. Its state is Not published, Waiting, Publishing, Published, Failed or Removed; after a failure it gives the kind of error and how many attempts failed. A Behind badge says the view doesn't show what is active now: a newer version was activated, a query a join reads activated a newer version, or the latest publish hasn't succeeded yet. The view reads the base table and the joined queries each time it is queried, without the live table's limits, so rows added to the base table in Databricks show in the view, not in Datahub. Someone with the export-manage role (datacatalog.export.manage) can Publish now, Remove view (it asks first) and read the SQL the view was published with and Databricks' own error message; everyone else sees the kind of error and is told who can. Publish now is refused on an archived asset.
When a publish fails. The status card names the reason in plain words.
- Datahub tries again on its own for a passing problem, a few times with growing pauses between attempts: Databricks out of reach, a timeout, or the credential vault unavailable. A stopped warehouse counts as starting up, not as a failure, and the publish waits for it.
- Other reasons need someone to change something first, and the card says who. For example, publishing turned off for the connection, or Databricks refusing the publishing login. A view is built with the access of the version's author; once the author can no longer sign in, an export manager's Publish now publishes it with their own access.
- Datahub never overwrites what it didn't create. If a table or view that Datahub didn't publish for this asset already has the view's name, the publish is refused: pick another view name. The same applies when another asset links the same view name on the same connection.
Who can read it. Datahub grants nothing on the view. Whoever can read the target schema in Databricks can read the view, and a view reads its source tables with the rights of its owner, the login that first published it. A grant someone makes on the view itself in Databricks is kept: a later publish changes the standing view in place instead of replacing it. The grant belongs to that view only: after Remove view, or under a new view name, the view is published again without it. An integrations admin chooses that login and that schema; see Administration → Publishing views to Databricks.
Removing it. Datahub never drops a view on its own: archiving the asset, or giving the view a new name, leaves the old view in Databricks. Remove view on the status card drops it, after checking it is still this asset's view. A version activated after that publishes the view again.
Working on a draft through an assistant¶
HERC, and any assistant connected over MCP, can work on an advanced asset for you. It reads the asset's joins, its live table, and what a draft changes: each changed cell with who changed it, and the rows the draft adds or removes. On a draft version it can also add, change or remove a join, add the columns a join brings in, Sync rows, promote a join's raw SQL to a governed query (the SQL the join already holds; you choose the name and the connection), change a cell, and re-run the rules. It does not change rules: that stays on the Rules subpage. A join it adds points at a governed query, never at SQL of its own. Everything it does runs with your roles, so it is refused wherever you would be, and a change it makes is recorded as yours. Rows reach the assistant only when your organisation's AI data-exposure setting and every connection the joins read allow it. When one is set to metadata only, the assistant says which setting holds the rows back instead of guessing a value.
Computed columns¶
A column can be computed: instead of holding stored data, it carries a formula evaluated
per row, with the other column names available as values. unit_price * quantity gives you a
line total without anyone typing it twice.
Formulas run in a sandbox, so the syntax is deliberately small:
- Text constants need quotes —
'pending'is the word;pendingis read as a column name. - Nested values use an index, not a dot —
payload["id"], notpayload.id. - Functions are a fixed list:
upper,lower,len,round,abs,int,float,str,concat,min,max,coalesce. Conditionals use thea if cond else bform. - A formula that cannot be evaluated leaves the cell blank rather than failing the row.
If you wrote a formula using a dot —
name.upper()rather thanupper(name)— it used to work and no longer does, and because an unusable formula yields a blank cell the change is quiet in the table. The platform logs each such formula once so an administrator can find them; rewrite them in the function form above.
Tags and what they do¶
Tags are not just labels. The platform uses them in:
- HERC — "find assets with PII tag" routes through tag search.
- Alerts — alert rules can target all assets carrying tag X.
- Workflows — workflow definitions can route reviews based on tags ("PII assets need an extra approver").
- Insights — KPI cards can filter "this dashboard's source assets that carry the finance tag".
- DNA — tag co-occurrence is one of the signals the knowledge graph uses to cluster assets.
Tags ship as a system table — /admin/system-tables → Tags. Tenant-defined tags sit alongside the platform defaults; the platform defaults can be edited but not deleted.
Documents¶
Attach a document to describe what an asset really contains. Upload a PDF, DOCX, TXT, MD, HTML, or CSV file (up to 50 MB), paste markdown, or link an external URL. A document can be attached to one or more assets, and each one runs an asynchronous processing pipeline before it becomes searchable.
flowchart LR
U["Upload<br/>PDF · DOCX · MD · HTML · CSV"] --> EX["Extract text"]
EX --> AN["Analyse<br/>summary · topics · language"]
AN --> CH["Chunk<br/>~500 tokens"]
CH --> SU["Summarise chunk"]
SU --> EM["Embed<br/>vector per chunk"]
EM --> RD(["Ready<br/>semantically searchable"])
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class EM accent
Figure 3 — What happens to a document after upload. The embedding step is what unlocks search by meaning; the AI steps are skipped gracefully when no provider is configured, and the file still lands as keyword-searchable text.
How a document becomes searchable
The AI steps — analyse, chunk, summarise, embed — need a configured AI provider and are skipped gracefully when one isn't available: the document still lands as keyword-searchable text, it just won't have semantic embeddings. Large PDFs (>50 pages) can take a minute; the current step is shown on the document row. When a viewer opens the asset, the Documents tab is searchable and HERC can answer "what does the customers table actually contain?" by reading the attached documents.
When a PDF cannot be read
Extraction handles the compressed and ASCII85-encoded streams that lab, certificate and other reporting systems produce. A page it still cannot read costs that page alone — the rest of the document is extracted and stays searchable. If no page can be read, the document lands as failed and the row states why, so you can tell an unreadable file apart from a platform problem. A scanned PDF that holds only page images has no text to extract; run it through OCR, or re-export it as a text PDF, before uploading.
Pages and sections in search results. Every search result names the document it came from (its file name and type). It also cites the page and the section it sits in, where the file carries them:
| File type | Page number | Section title |
|---|---|---|
| Yes | From the PDF's bookmarks (its outline). A PDF without bookmarks has no section titles. | |
| DOCX | No (a Word file has no fixed pages) | From Word heading styles (Heading 1, Heading 2, … and Title), including your own styles based on them. |
| MD | No | From Markdown headings (# Scope, or a line underlined with === / ---). |
| TXT, CSV, HTML | No | No |
A result's section is the last heading at or before where its passage starts. Text before a document's first heading has no section. A PDF bookmark is matched to where its title is printed on the page it points to. When the bookmark's wording differs from the printed heading, the section starts just after the previous heading on that page instead.
Documents uploaded before page numbers and section titles were recorded
Documents keep what they were processed with. To fill in page numbers and section titles on an older document, reprocess it with the Reprocess button on its row in the asset's Documents list. You confirm first: reprocessing reads the stored file again, replaces the document's chunks, and re-runs the AI analysis, so a summary or topics you edited by hand are replaced, and the run uses AI model calls. While a document is being processed it cannot be reprocessed again. HERC can do the same with the reprocess_document tool. Over an MCP connection that tool is available to the Administrator persona by default. Reprocessing needs datacatalog.assets.write.
Finding documents by meaning. Search runs in three modes — semantic (vector similarity), keyword (full-text), and hybrid (a blend of both, the default). You can narrow with metadata filters (tags, document type, date), tune the similarity threshold, and every result is permission-scoped, so a search only returns documents the viewer is allowed to see (organisation / restricted / public visibility).
Linking assets to other entities¶
| Link | Where to set it up | Why |
|---|---|---|
| Tag | Asset detail → Tags chip selector | Classify the asset for search, alerts, workflows. |
| Glossary term | Asset detail → Terms tab → Add term (or from the term side: term detail → Linked assets) | Bind a business definition to a physical dataset. |
| Data Product | Asset detail → Register as Data Product | Wrap the asset to put it on a contract. |
| Document | Asset detail → Documents tab → Attach document | Add a description / runbook / ERD. |
| Lineage upstream/downstream | Inferred automatically when the asset is referenced by another entity (metric, alert, dashboard). | The lineage tab shows the graph. |
Roles¶
| Role | Capability |
|---|---|
datacatalog.assets.read |
View assets, columns, documents, lineage. |
datacatalog.assets.write |
Create / edit / archive assets, attach tags, attach documents. |
datacatalog.assets.approve |
Approve published assets. |
datacatalog.export.manage |
Configure Catalog export targets (e.g. push to a downstream catalog), choose which assets they receive, and sync an asset to them. Also Publish now and Remove view for an advanced asset's Databricks view, and read its SQL and errors. Held by administrators by default. Without it the asset page shows which targets an asset goes to and whether a copy is behind, but offers no sync. |
datacatalog.queries.manage |
Create and edit governed queries — including promoting an advanced asset's raw SQL into one. Held separately from datacatalog.assets.write: Catalog.Editor does not carry it, so an editor can write and save raw SQL but needs a steward to promote it. |
Default role groups: Catalog.Viewer, Catalog.Editor, Catalog.Approver, Catalog.Admin.
An asset in a domain is edited by that domain's groups
Once an asset is filed into a domain, datacatalog.assets.write lets you edit it only
when one of your role groups works in that domain. Outside it, the page opens read-only:
no pencil, no Submit for review, no version actions, and the Advanced tab shows the
configuration without letting you change it. The header says Editing · Outside your
domains, with the reason a click away. You can still read everything, drafts included.
An asset with no domain stays open to every writer. See Domains.
Limitations¶
| Limit | Why | Workaround |
|---|---|---|
| The Catalog stores metadata, not data. | We are not your warehouse — we describe it. | Connect a warehouse via the Metadata Engine; the rows live there. |
| Lineage is inferred from explicit references. | We don't parse arbitrary SQL files looking for joins. | Define metrics on the join — that produces explicit lineage. |
| Documents are chunked by the platform, not by the author. | Manual chunking doesn't scale across thousands of docs. | Author sections with real headings: Word heading styles, Markdown # headings, PDF bookmarks. Each chunk is labelled with the section it starts in. |
| Vector search depends on having an AI provider configured. | Embeddings need a model. | Configure a provider, or use plain keyword search. |
| Bulk-archive is gated by per-asset confirmation. | Bulk archive of governed assets is a footgun. | Run the archive in batches; the platform retains undo (restore) up until permanent delete. |
| An advanced asset's synced or exported file can be missing values for remote (locked) columns. | Export/sync reads your asset's own stored rows — it doesn't re-run the live warehouse query the table view does. | A value only appears in exports once a rule or a manual edit has actually saved it to the asset. For the values as the live table shows them, use Export CSV on the Live table. |
Audit & compliance¶
| Question a CISO might ask | Where to look |
|---|---|
| "Which assets are tagged PII?" | /data-catalog/assets filtered by tag PII. |
| "Who approved the customers asset publish?" | Detail → audit history. |
| "Who changed, archived or restored this row?" | Detail → History. Every change to a row names the person who made it, including bulk edits and bulk archives. Changes recorded before this was added show System. A row's entry reads Row followed by its key (for example Row · 42), an archived row says Archived and a restored one Restored, and a version's entry reads Version. |
| "Who took PII off this asset?" | Detail → History tab: each change to the asset's tags reads Tags changed, names who made it and which tags were added and removed. The Audit log shows the same entries across all assets. |
| "How do we ensure new PII columns don't slip through?" | Configure a workflow that routes assets carrying a PII column to an extra approver step in /admin/workflows. |
| "Where do uploaded documents live?" | In your tenant's PostgreSQL datacatalog.documents (text + embeddings via pgvector). Files attached as binary blobs. |
| "Can we pull the catalog into our other tools?" | Yes — configure an Export Target in /admin/export-targets. Standard formats supported (OpenLineage, ODCS). |
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| An asset opens read-only although you hold the write role; the header says Editing · Outside your domains | The asset is filed into a domain none of your role groups work in. | Ask whoever manages that domain to add one of your groups to it (Manage members on the domain's page). |
| Bulk import preview shows "Validation failed" | Required columns missing or status invalid. | The preview shows per-row errors; fix in the file and re-upload. |
| A record is refused with "Column 'qty': expected integer, got str '4.50'" | The value you sent, quoted at the end, does not fit the column's type. A bulk edit names only the values you entered. A violation on the Records tab, on a row already stored, does not name its value, as in "expected integer, got str": the row itself shows it. Only a date, date and time or uuid column quotes the text it cannot read, as it always did. | Send a value of the column's type, or change the column's type on the Schema tab. On a versioned asset, do this in a draft. |
| A record or an import is refused with "Column 'price': 'Infinity' is not a number a table can hold (use a regular number or leave it empty)" | A decimal or coordinate column was given NaN or Infinity, as a number or as text such as "Infinity", "-inf" or "1e999" (too large for any table). A flow's Save to table step refuses it in the same words. | Send a regular number, or leave the cell empty. |
| Import or bulk update says Start a draft first | The asset is versioned, and an import writes into its draft only. It has no draft now: it was published or discarded, or a version is under review. | Close the import and start a new version from the asset's header, then import again. If a version is under review, wait until that review is finished or withdrawn. |
| Import is refused with "over the 25 MB limit" | The file exceeds the per-upload cap. | Split the file, drop columns you are not importing, or connect a Metadata Engine source for warehouse-scale data. |
A record added through the API or an AI agent needs a unique_id |
An import that finds no key column adds a unique_id key (a uuid). |
Leave it out: a new one is generated, as the Records tab does. To make a retry safe, send your own uuid: a second add with the same key is refused instead of adding the row twice. |
| A record is refused with "must be one of" | The column has an allowed-values restriction. An import can set one from the values in its file. | On the asset's Schema tab, edit the column, choose Remove restriction and save the schema. On a versioned asset, do this in a draft. Don't tick Allow new values on a date column: it swaps the date picker for free text. |
| A table created from a file opened with no rows | Its file is still importing in the background, or that import failed. | Wait for the import's entry in the Notifications bell: it names how many rows were imported, or why the import failed, also if you closed the tab that started it. If it failed, nothing was imported and the table keeps the columns read from the file: fix the file, or a column's type on the Schema tab, and import it again with Import data on the asset's page. If the server stopped during the import, the entry says so: import the file again. If a notice in the tab says the import could not be followed to its end, wait for the bell's entry; the rows that arrived are on the asset's Records tab. |
| The create window says the import could not be started | The platform could not start the background import, so no rows were imported. The new table and its columns were kept. | Choose Confirm import again in the same window. Don't create the table again: that makes a second, empty table. |
| Import says the server is busy and to retry | Two imports are already running; yours waited its turn and was asked to come back rather than time out silently. | Retry in a moment. |
| Document embed status stays processing | The AI provider is down or the file is huge. | Check /admin/audit-log for datacatalog.document.embed_failed; retry from the document row. |
| Semantic search returns nothing | Embeddings aren't ready yet, or no AI provider is configured. | Wait for the document to reach Ready, or configure a provider; keyword search still works without one. |
| Search results show no page or section | The file type carries none (see Pages and sections in search results), or the document was processed before they were recorded. | Reprocess the document from its row. A PDF needs bookmarks for section titles, and a Word file needs heading styles. |
| Tag is missing from the selector | It's not in the system table. | Admin → /admin/system-tables → Tags → add. |
| Asset's Lineage tab is empty | Nothing references this asset yet. | Bind a metric, build an insight card, or attach an alert to populate lineage. |
| Submit for Review button greyed | You don't have datacatalog.assets.write, or required fields are missing. |
Check role; complete description, owner, type. |
| A version can't be submitted, applied or discarded, or versioning can't be switched off: "This asset is under review to be published" | The asset itself is under review for its first publish, and that review covers v1. | Wait until the review is finished. If it is rejected, v1 is a draft again and you can keep editing it, discard it or switch versioning off. |
| Submit for Review is refused: "This asset is published by approving its draft version" | The asset is published through a version review instead: it is an advanced asset (its first version carries its joins and rules), or one of its versions is already under review. | Use Submit Draft for Review on the asset's header or Versions tab, or wait for the version review already open. |
| An advanced asset's table says it is waiting for the warehouse | The Databricks SQL warehouse its joins run on had stopped and is starting. | Wait a few minutes. The rows load by themselves once the header's Warehouse slot reads Online. |
Arriving from a domain's detail page narrows this list to that domain automatically — a banner names it, with a one-click way back out. See Domains.
See also¶
-
Terms that describe what assets mean; they link back to catalog assets.
-
Discover schemas in a warehouse and snapshot them; promote to catalog assets.
-
Wrap an asset to put it on a contract.
-
Assets are nodes in the knowledge graph.
-
Natural-language search across the catalog.