Changelog
OpenMetadata 2.0.2 is a maintenance release focused on connector reliability across Oracle, Databricks, Snowflake, BigQuery, Clickhouse, KafkaConnect, Grafana, and StarRocks, MCP tool consolidation and hardening, a governance rollout that restricts direct team membership to Group teams, several XSS and access-control fixes, and a broad security dependency cleanup.
🔌 Connectors & Ingestion
- REST/OpenAPI: array properties with an inline object schema emitted a synthetic
item: UNKNOWNchild #32007: Expands the item's properties with their OpenMetadata types and descriptions instead. - REST/OpenAPI: API collections and endpoints could ingest out of order #31852: Persists all API collections before ingesting endpoints, so endpoints no longer reference a collection that hasn't been committed yet.
- KafkaConnect: topic-namespace membership was emitted as lineage #32207: Topic-namespace membership is no longer misreported as a lineage edge.
- KafkaConnect: Confluent Cloud managed connectors resolved no topics, and telemetry credential failures logged the same line whatever the cause #32512, #32999: Topics are now resolved from Confluent's Telemetry API, and the warning distinguishes a 401 from a 403 with Confluent's own error detail.
pygtrie2.6 brokeimport airflowon Python 3.10 #32378: Capspygtriebelow 2.6 so ingestion imports Airflow correctly.- Databricks: SQL-defined DLT pipelines had no lineage extracted #31654: Lineage is now extracted from SQL-defined DLT pipelines.
- Databricks: Unity Catalog access rows incorrectly linked a table to itself #32214: Legitimate access-not-derivation rows (a streaming or CDC write touching its own target table) no longer create a self-referencing lineage edge.
- Databricks: large workspaces failed to ingest all jobs #33204: Jobs are now paginated by token, so large workspaces ingest in full.
- Clickhouse: materialized views had no downstream lineage #32314: Downstream lineage is now created for materialized views.
- Oracle: query history failed with
ORA-00933on Oracle 11g #32310: Query history now works against Oracle 11g. - Oracle: CHAR length semantics were lost in the reflected column type #32306: CHAR length semantics are now preserved during reflection.
- Athena: assume-role credentials were never refreshed #32853: Assume-role credentials now refresh correctly.
- Snowflake: query tags mutated the configured connection arguments #32481:
QUERY_TAGis now applied through the driver session parameters at connection creation. - BigQuery: multi-project ingestion with ADC or a credentials file always connected to the first project #32846: Each database iteration is now scoped to the project it is ingesting.
- Doris: identifiers in generated SQL were unquoted #32443: Doris identifiers are now quoted.
- Grafana: panels nested inside collapsed rows were skipped #32825: Collapsed-row panels are flattened before chart and lineage ingestion.
- Airflow: dynamically mapped tasks produced no lineage #32818:
inlets/outletsserialized insidepartial_kwargsare now read when the top-level keys are empty. - Protobuf schemas whose message didn't match the topic name failed to parse #32449: Parsing falls back to the sole top-level message, keeps ambiguous schemas unresolved, and supports well-known imports.
- Domo and Astra connection fields diverged from the password-field conventions #32545: Both are aligned, and stored connection values are restored on update.
- Kubernetes ingestion pipelines couldn't decrypt the ingestion-bot JWT token #32708: The token is now correctly deserialized and decrypted.
- A bad
SERVICE_TYPE_REFlookup result went unvalidated #32739: The result is now validated inget_reference_type_from_service_type. - The Kubernetes exit handler could match its own pod as the main pod #32743: The exit handler no longer matches itself.
- Looker: data-model lineage failed on the first run #32367: The sink's bulk buffer is now flushed before anything looks up a data model.
- Tableau: auto-titled mirror columns were ingested as duplicates #32301: Mirror columns are now collapsed.
- Spark services offered a Metadata Agent that cannot work #32834: Spark metadata is pushed by the Spark Agent, so pull-based extraction is now marked unsupported.
- StarRocks: lineage builds produced unresolvable FQNs #32543: FQNs now resolve correctly during lineage builds.
📊 Data Quality
- Databricks profiler: remaining SQL failures #32441: Resolves the remaining SQL failures in the Databricks profiler.
- The test case picker didn't handle request failures #32514: Request failures in the test case picker are now handled gracefully.
- No way to soft delete and restore test cases #32349: Adds UI support for soft deleting and restoring test cases.
- BigQuery: STRUCT profiler columns weren't attached #32549: STRUCT profiler columns are now attached correctly.
- Doris: profiler datetime partition filters weren't Doris-compatible #32788: Adds Doris dialect compilation for
DatetimeAddFnandTimestampAddFn. - Data Insights showed wrong numbers with no error, and one chart path returned a 500 #32115: Declares each data asset type once instead of in three separate places, fixing four silently-wrong metrics and the 500.
- Sample-data validation timeout wasn't forwarded across
docker exec#31710: The configured timeout now propagates correctly. - Contracts:
qualityScorecame backNaNwhen every referenced test was soft-deleted #32750:qualityScoreno longer breaks when referenced tests are soft-deleted. - The contract status badge didn't reflect the actual status #32964: The badge is now driven off the actual contract status.
TestSuiteDetailsPageshowed no error state on fetch failure #32746: A fetch failure now renders an error state instead of a blank page.- Profiler partitioning was built from stale form state #33117: Partitioning is now built from the current form values.
- Auto-classification did nothing when sample data was disabled #32607: With no sampled fields, metadata leaf columns are now traversed so column-name recognizers still run.
- Test Cases pagination wasn't reset when search or filters changed #33335: Pagination now resets to page one on search or filter changes.
🔍 Search & Discovery
name.keywordwasn't exposed, and removed search fields couldn't be re-added #32369:name.keywordis now exposed, and removed search fields can be re-added.- Embedding token usage was discarded instead of reported #32552: Embedding token usage is now reported.
- Semantic search embedded ElasticSearch queries as documents instead of queries #32553: Queries are now embedded as queries, improving semantic search relevance.
- A single-writer reindex pipeline was needed for RDF #33098: Backports a single-writer RDF reindex pipeline to prevent concurrent-write conflicts.
- Ranking could throw an NPE on Lucene 10 when a segment had zero matches #33292:
script_scorenow guards against zero-match segments.
🛡️ Data Governance & Quality
- Governance workflow edge conditions and node references were interpolated unchecked into Flowable expressions #32370: Conditional-edge conditions and source nodes are now validated at the create/update boundary.
- Direct users could be assigned to non-Group teams through the API or the team dropdown, then couldn't be removed, added through the UI, or exported #32372, #32915: Direct memberships are now rejected for Department, Division, and BusinessUnit teams, and team dropdowns offer only Group teams.
- Migration: existing direct-user memberships on non-Group teams from before the fix above stayed invalid #33352: A 2.0.2 migration cleans up the pre-existing invalid memberships automatically.
- Non-Group team Users tabs showed no members after direct membership was restricted #33354: The Users tab now rolls up members from sub-groups instead.
- Bot list responses omitted the required
botUserrelationship #32398: The relationship is now batch-loaded for list responses, so SDKlist_all_entitiescalls can deserializeBotentities. - App endpoint permission checks didn't match the platform RBAC model #32427: App endpoints now align with platform RBAC, and App patch is authorized before the entity lookup.
- Broken access control on the glossary-term bulk asset endpoints #32539:
assets/addandassets/removenow authorizeEDIT_GLOSSARY_TERMSon each target asset instead of bypassing the authorizer. - Cross-user follower changes were unrestricted #32322: Follower endpoints now reject a null
userId, compare against the authenticated subject, and require admin authorization for cross-user mutations. - OpenMetadata accepted a URL without an http(s) scheme #32542: URLs without an http(s) scheme are now rejected.
- Pub/Sub credentials weren't masked correctly #32135: Converts persisted Pub/Sub credentials to their generated schema classes before masking and unmasking, so they're consistently protected.
- Overriding metadata merged tags instead of replacing them #32496: A bot bulk PUT that explicitly supplies tags now replaces existing tags when
overrideMetadatais set, instead of merging them. - No way to export classification and tag-level data #31938: Adds export support for classification and tag level.
- Bot searches didn't apply the caller's policies #32460: Bot searches now apply the caller's policies.
- The search dropdown option label was set through
dangerouslySetInnerHTML#32572: The highlighted label is parsed into React nodes from a sanitized string instead. stringToHTMLrendered stored user content unsanitized #32951: The helper now routes throughDOMPurify.sanitize().- A DOMPurify bypass in math equations, and an XSS in the mention dropdown #32896: Both are closed.
- Airflow API responses leaked internal diagnostics #32850: Responses are now generic. Diagnostics remain in the logs.
🔗 Lineage
- Impact Analysis pagination wasn't reset when search or quick-filters changed #32699: Pagination now resets to page one.
- Changing the Upstream/Downstream Depth in the lineage settings modal did nothing #33299: The setting now writes to the shared lineage store, so changing it correctly refetches the graph.
🤖 MCP Server / Automations
- The MCP tool surface had 24 overlapping tools #32072: Merges overlapping tools down to 15.
- MCP Knowledge Page creation was broken #32209: Knowledge Page creation now works through MCP.
- MCP mishandled unknown methods and initialized notifications #32147: Both are now handled per the MCP protocol.
- MCP tools bypassed lineage authorization #32437: Lineage authorization is now enforced in MCP tools.
- MCP entity patch requests mishandled the entity lifecycle #32226: MCP entity patch lifecycle handling is fixed.
- The MCP connector used an unsupported ingestion transport #32342: The MCP connector now uses HTTP transport.
- An owner could be rejected with a 403 reading their own private memory #32858: The owners relationship is now hydrated before the private-memory visibility check runs, even when the request didn't project
owners. - AI context trust signals and MCP context-memory visibility were missing #32261, #32465: Both are added.
🔐 Authentication
- SSO role changes at the identity provider weren't reflected in OpenMetadata #32961: SSO roles now sync from the provider's
id_tokenat the OIDC callback. - OIDC login could issue a zero-lifetime token #33251: Zero-lifetime OIDC login tokens are now prevented.
⚙️ Platform
catalog.logduplicated every rotatedopenmetadata.logline #32366: Log rotation no longer duplicates lines intocatalog.log.- Logs failed to render on Kubernetes 1.36+ #32504: Logs now render correctly on Kubernetes 1.36 and later.
🎛️ UI
- The Queries tab showed the parent table's description provenance instead of its own #32292: The Queries tab now shows the correct provenance.
- A second domain tag update returned a 400 #32358: A second update to a domain tag no longer fails.
- No pagination for large glossaries #32223: Adds cursor-based Prev/Next pagination and paged expand-all for glossary terms.
- Math equations were silently stripped on save #32313: Preserves
<block-math-equation>nodes through both the frontend and backend sanitizers. - The metric version page crashed into the error boundary #32794:
UnitOfMeasurementwas a type-only import, so it was erased at build time and threw at runtime. It's now imported as a value. - The Data Product "Add Assets" picker ignored the Domain Validation rule #32336: The picker lists assets across all domains when the rule is disabled, and stays domain-scoped when it's enabled.
- The glossary term-not-found state used an inconsistent placeholder #32865: The term-not-found state now uses the shared
NoDataPlaceholdercomponent. - No way to filter team assets by entity type, and quick-filter removal was broken #32807: Adds an Entity Type filter to team assets and fixes quick-filter removal.
- The Data Product Reviewers field showed in OSS #32914: The field is now hidden in OSS, since it's a Collate-only capability.
- The Data Product grid card had no Description field #32948: Adds a Description field to the grid card and restyles its labels.
- The Glossary Terms zero-result state ignored active filters #32857: The empty state is now filter-aware.
- The entity-type trigger didn't receive focus before its listbox opened #32969: Focus now moves to the trigger first.
- Context Center: the article Data Products panel and domain save had bugs #33081: Both are fixed.
- Advanced Search lowercased tag-like option casing #33220: Tag-like options now show their original casing.
- The entity hover card could outlive its trigger, and a 403 looked identical to an empty result #33205: The hover card now closes when its trigger is gone, and a 403 is now told apart from a genuinely empty response.
- The Topic page showed nothing on sustained fetch failures #32736: The Topic page now shows an error placeholder.
TierCard's selected tier wasn't reset on close #33115: Closing the card now resetsselectedTier, preventing stale radio state.- The table-type custom property editor lost user data when a column was named
id#32741: User data is now preserved regardless of column name. - Clicks on Domain and Data Product listing rows could be intercepted by a nested link or an overlay #33267, #33022: Row clicks and the pointer cursor now work correctly, and overlays no longer swallow clicks meant for the row.
🔒 Security
@humanfs/node→ 0.16.8 #32561.- Jackson for CVE-2026-83557 and CVE-2026-19032 #32813.
fast-uri→ 3.1.7 #32870.js-yaml→ 5.4.1 #32913.- Jetty → 12.1.12 #33026.
@tiptap/*→ 2.27.3 for amergeAttributesprototype-pollution vulnerability #33035.- Vulnerable Debian packages upgraded in ingestion images #33321.
- Netty → 4.2.18.Final and Freemarker → 2.3.35 for CVE-2026-89044 and CVE-2026-84939 #33327.
📣 Notifications
- Bulk entity updates wrote no change event, so
Get Schema Changesalerts never fired on metadata ingestion #32350: The bulk path now captures the incremental change description, so bulk updates both alert and audit. - A
Pipelinealert filtered toFailedre-notified forever and backfilled on creation #32181: Re-ingested and historical runs no longer emit change events. - A single unevaluable event discarded its whole change-event batch #32953: One bad event no longer takes down the rest of the batch.
Full Changelog: 2.0.1...2.0.2