Skip to content

feat: column name hashing in FQN construction#26950

Open
mohittilala wants to merge 8 commits intomainfrom
column-name-hashing
Open

feat: column name hashing in FQN construction#26950
mohittilala wants to merge 8 commits intomainfrom
column-name-hashing

Conversation

@mohittilala
Copy link
Copy Markdown
Contributor

Describe your changes:

Fixes https://github.com/open-metadata/openmetadata-collate/issues/3253

Summary

Implements column name hashing to decouple FQN storage constraints from raw column names. Column names from sources like BigQuery structs and Snowflake can exceed entityLink VARCHAR(3072) limits when used directly in FQNs. This is the long-term fix for ingestion failures previously patched in #26530.

Approach: Hash only the column segment in FQN construction. column.name stays as the raw readable source name, column.fullyQualifiedName uses md5_<32 hex chars> for column segments.

BEFORE: name = "customer_email" FQN = "svc.db.schema.tbl.customer_email"
AFTER: name = "customer_email" FQN = "svc.db.schema.tbl.md5_a1b2c3d4..."

Why this approach:

  • name is the column identity — EntityUtil.columnMatch uses it for re-ingestion matching
  • displayName is user-editable — can't be sole store of original name
  • Profiler, PII scanner, search all use col.name directly — completely unaffected
  • FQN is a derived field — the right place to apply hashing

Changes

Core

  • New ColumnNameHash utility (Java + Python) — MD5-based, consistent with existing EntityUtil.hash()
  • ColumnUtil.setColumnFQN(), ContainerRepository, TableRepository joins — hash column name before building FQN
  • Python fqn.py Column builder — hash column_name parameter
  • validateColumn() — supports both raw names and hashed segments
  • resolveColumnName() — reverse lookup from hash to readable name for API responses

Cleanup

  • Deleted truncate_column_name() and removed from 12 connector/dashboard files
  • Removed columnName pattern constraint (:: prohibition) from table.json
  • Removed ColumnName, ColumnProfile, CustomColumnName from reserved keyword encoding

Data Quality

  • test_case_runner.py, sqa_validator_mixin.py, pandas_validator_mixin.py — hash-based fallback when matching columns from entity links
  • entity_link.py — hash column name when converting entity link to FQN

Migration (v1.13.0)

  • Recomputes all column FQNs with hashed segments across tables, dashboard data models, and containers
  • Updates test case entity links with hashed column identifiers
  • Idempotent — skips columns with already-hashed FQN segments

Frontend

  • Lineage modal and lineage table — resolve readable column name from entity data instead of extracting hashed FQN segment
  • Task feed cards, tag/description components — use column.name when building entity links
  • Added fromColumnName/toColumnName to ColumnLevelLineageNode interface

What is NOT affected

  • Profiler SQL queries — uses col.name (raw)
  • PII/Classifier regex scanning — uses col.name (raw)
  • Column matching on re-ingestion — columnMatch uses name (raw)
  • Search indexing — indexes col.getName() (raw)
  • Column display in UI — uses getEntityName() (raw)

Test plan

  • 59 Python tests passing (31 new hash tests + 28 updated FQN special chars tests)
  • Cross-language hash verification (Python MD5 matches Java EntityUtil.hash())
  • Java formatting via mvn spotless:apply
  • Ingestion E2E with columns containing ::, >, ", unicode, and 1000+ char names
  • Re-ingestion — verify column matching and metadata carryover (tags, descriptions)
  • Profiler runs correctly with hashed column FQNs
  • Data quality test case resolution with hashed entity links
  • Search returns results when searching by original column name
  • Migration on existing data — verify FQN recomputation and idempotency
  • Frontend lineage and task display shows readable column names

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

Copilot AI review requested due to automatic review settings April 2, 2026 03:35
@mohittilala mohittilala requested review from a team as code owners April 2, 2026 03:35
@github-actions github-actions bot added Ingestion safe to test Add this label to run secure Github workflows on PRs labels Apr 2, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements hashed column-name segments in column FQN construction (using md5_<32hex>) to prevent long/raw column names from exceeding entityLink VARCHAR(3072) limits, and updates backend/ingestion/UI code paths to work with hashed column FQNs while keeping Column.name readable.

Changes:

  • Backend: Introduces ColumnNameHash, hashes column segments when building column FQNs, updates joins + validation to support raw or hashed identifiers, and adds a v1.13.0 data migration to recompute stored column FQNs and test-case entity links.
  • Ingestion: Hashes the column segment when building FQNs, hashes entity-link → FQN conversions, removes column-name truncation, and updates/extends unit tests for hashing + special characters.
  • UI: Prefers column.name for building entity links and attempts to resolve readable column names in lineage views/modals instead of showing hashed FQN segments.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx Prefer column.name over parsing the column name from FQN when building entity links.
openmetadata-ui/src/main/resources/ui/src/utils/Lineage/LineageUtils.tsx Adds column-name lookup by column FQN to populate readable lineage table values.
openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx Updates lineage delete-modal text to resolve readable column names from node data when possible.
openmetadata-ui/src/main/resources/ui/src/context/LineageProvider/LineageProvider.tsx Passes ReactFlow nodes into getModalBodyText for column-name resolution.
openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx Build column entity links using columnData.name when available.
openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx Displays resolved fromColumnName/toColumnName in lineage column tables (fallback to FQN segment).
openmetadata-ui/src/main/resources/ui/src/components/Lineage/Lineage.interface.ts Extends ColumnLevelLineageNode with fromColumnName/toColumnName.
openmetadata-ui/src/main/resources/ui/src/components/Database/TableDescription/TableDescription.component.tsx Build column entity links using raw column name when available; fixes memo deps.
openmetadata-spec/src/main/resources/json/schema/entity/data/table.json Removes :: prohibition pattern from columnName schema.
openmetadata-service/src/main/java/org/openmetadata/service/util/ColumnNameHash.java New backend utility for hashing/resolving column FQN segments.
openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1130/MigrationUtil.java Adds v1.13.0 migration logic to recompute column FQNs and update test-case entity links.
openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1130/Migration.java Runs the new column-FQN migration for Postgres.
openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1130/Migration.java Runs the new column-FQN migration for MySQL.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java Hashes column segment when persisting joins; resolves join column names back to raw for API output.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java Updates validateColumn to accept raw names or hashed column segments.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ColumnUtil.java Hashes column segment during setColumnFQN(...) for columns and nested children.
ingestion/tests/unit/utils/test_fqn_special_chars.py Updates special-character column FQN expectations to hashed column segments.
ingestion/tests/unit/utils/test_column_name_hash.py New unit tests validating hashing behavior and MD5 compatibility.
ingestion/src/metadata/utils/fqn.py Hashes column_name for Column FQN building; stops reserved-keyword encoding for column segments.
ingestion/src/metadata/utils/entity_link.py Hashes column segment when converting entity links to column FQNs if not already hashed.
ingestion/src/metadata/utils/datalake/datalake_utils.py Removes column-name truncation from datalake column extraction.
ingestion/src/metadata/utils/column_name_hash.py New ingestion utility for hashing and detecting hashed column segments.
ingestion/src/metadata/ingestion/source/database/json_schema_extractor.py Removes column-name truncation when creating columns from JSON schema.
ingestion/src/metadata/ingestion/source/database/glue/metadata.py Removes column-name truncation for Glue columns.
ingestion/src/metadata/ingestion/source/database/column_helpers.py Deletes the truncate_column_name helper implementation.
ingestion/src/metadata/ingestion/source/dashboard/tableau/metadata.py Removes column-name truncation for Tableau columns.
ingestion/src/metadata/ingestion/source/dashboard/superset/mixin.py Removes column-name truncation for Superset columns.
ingestion/src/metadata/ingestion/source/dashboard/sigma/metadata.py Removes column-name truncation for Sigma columns.
ingestion/src/metadata/ingestion/source/dashboard/quicksight/metadata.py Removes column-name truncation for QuickSight columns.
ingestion/src/metadata/ingestion/source/dashboard/qliksense/metadata.py Removes column-name truncation for QlikSense columns.
ingestion/src/metadata/ingestion/source/dashboard/powerbi/metadata.py Removes column-name truncation for PowerBI columns/measures.
ingestion/src/metadata/ingestion/source/dashboard/microstrategy/metadata.py Removes column-name truncation for MicroStrategy columns.
ingestion/src/metadata/ingestion/source/dashboard/microstrategy/helpers.py Removes column-name truncation for MicroStrategy parsing helper.
ingestion/src/metadata/ingestion/source/dashboard/looker/columns.py Removes column-name truncation for Looker columns.
ingestion/src/metadata/ingestion/models/custom_basemodel_validation.py Removes reserved-keyword encoding entries for column-name-related wrapper models.
ingestion/src/metadata/data_quality/validations/mixins/sqa_validator_mixin.py Adds hash-based fallback when resolving columns from entity links.
ingestion/src/metadata/data_quality/validations/mixins/pandas_validator_mixin.py Adds hash-based fallback for dataframe column resolution.
ingestion/src/metadata/data_quality/processor/test_case_runner.py Adds hash-based fallback when matching test-case column entity links to table columns.
Comments suppressed due to low confidence (1)

ingestion/src/metadata/data_quality/processor/test_case_runner.py:358

  • column can still be None here (e.g., when neither the raw name nor the hashed fallback matches any table column). The subsequent column.dataType / column.name access will then raise an AttributeError. Add an explicit guard after the lookup (raise a clear error or mark the test case as incompatible and continue) before dereferencing column.
            if column.dataType not in test_definition.supportedDataTypes:
                self.status.failed(
                    StackTraceError(
                        name="Incompatible Column for Test Case",
                        error=f"Test case {tc.name.root} of type {test_definition.name.root}"

Comment on lines +107 to 110
if not is_hashed_column_fqn_segment(col_segment):
col_segment = hash_column_name(col_segment)
return f"{split_entity_link[1]}.{col_segment}"

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split() returns the raw entity-link segment, which may still be URL-encoded (spaces/unicode/special chars). Hashing col_segment without decoding can produce a different hash than the one generated from the actual column name, causing mismatched FQNs. Decode/unquote the column segment (same way as get_decoded_column) before hashing or checking is_hashed_column_fqn_segment.

Suggested change
if not is_hashed_column_fqn_segment(col_segment):
col_segment = hash_column_name(col_segment)
return f"{split_entity_link[1]}.{col_segment}"
decoded_col_segment = unquote_plus(col_segment)
if not is_hashed_column_fqn_segment(decoded_col_segment):
decoded_col_segment = hash_column_name(decoded_col_segment)
return f"{split_entity_link[1]}.{decoded_col_segment}"

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +65
const columns = (entityData as unknown as { columns?: Column[] }).columns;
if (!columns) {
return undefined;
}
const match = columns.find((col) => col.fullyQualifiedName === columnFqn);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lookup only checks the top-level columns array and ignores nested children. For structured columns, this will fail to resolve and will fall back to displaying the hashed FQN segment in the lineage UI. Consider performing a recursive search across columns/children (similar to findColumnByEntityLink in TableUtils.tsx) and add a type guard instead of the unknown cast so the function behaves predictably when entityData doesn't include columns.

Copilot uses AI. Check for mistakes.
Comment on lines +276 to +280
for (const node of nodes) {
const columns: Column[] = node.data?.node?.columns ?? [];
const match = columns.find(
(col) => col.fullyQualifiedName === columnFqn
);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only searches node.data.node.columns at the top level. If the lineage column FQN corresponds to a nested/child column, the modal will fall back to getPartialNameFromTableFQN(...) and show the hashed segment. Update the lookup to traverse Column.children recursively when matching by fullyQualifiedName.

Copilot uses AI. Check for mistakes.
Comment on lines +687 to +692
render: (columnFqn: string, record: SourceType) =>
columnNameRender(
columnFqn,
record as unknown as ColumnLevelLineageNode,
'fromColumnName'
),
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The render function relies on record as unknown as ColumnLevelLineageNode to access fromColumnName. This hides type mismatches and can break silently if the table dataSource changes. Prefer typing columnImpactColumns as ColumnsType<ColumnLevelLineageNode> (and the corresponding dataSource) so the renderer receives the correct record type without unknown casts.

Copilot uses AI. Check for mistakes.
Comment on lines +717 to +722
render: (columnFqn: string, record: SourceType) =>
columnNameRender(
columnFqn,
record as unknown as ColumnLevelLineageNode,
'toColumnName'
),
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above for toColumnName: the unknown cast defeats type safety. Adjust the column table typing (columns + dataSource) so record is a ColumnLevelLineageNode here and remove the cast.

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +214
Column firstColumn = columns.get(0);
if (firstColumn.getFullyQualifiedName() == null) {
return false;
}
String fqn = firstColumn.getFullyQualifiedName();
String lastSegment = fqn.substring(fqn.lastIndexOf('.') + 1);
return ColumnNameHash.isHashedColumnFQNSegment(lastSegment);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

columnsAlreadyHashed only inspects the first column’s FQN segment. If the first entry is already hashed but other columns (or nested children) are not, the migration will incorrectly skip the entity and leave mixed/legacy column FQNs. Consider checking all columns (and recursively their children) for a hashed last segment, or recompute unconditionally when any column is not hashed.

Suggested change
Column firstColumn = columns.get(0);
if (firstColumn.getFullyQualifiedName() == null) {
return false;
}
String fqn = firstColumn.getFullyQualifiedName();
String lastSegment = fqn.substring(fqn.lastIndexOf('.') + 1);
return ColumnNameHash.isHashedColumnFQNSegment(lastSegment);
for (Column column : columns) {
if (!isColumnAndChildrenHashed(column)) {
return false;
}
}
return true;
}
private static boolean isColumnAndChildrenHashed(Column column) {
if (column == null) {
return false;
}
String fqn = column.getFullyQualifiedName();
if (fqn == null) {
return false;
}
String lastSegment = fqn.substring(fqn.lastIndexOf('.') + 1);
if (!ColumnNameHash.isHashedColumnFQNSegment(lastSegment)) {
return false;
}
List<Column> children = column.getChildren();
if (!nullOrEmpty(children)) {
for (Column child : children) {
if (!isColumnAndChildrenHashed(child)) {
return false;
}
}
}
return true;

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +42
def is_hashed_column_fqn_segment(segment: str) -> bool:
"""Check whether a string is a hashed column FQN segment."""
return (
segment is not None
and segment.startswith(HASH_PREFIX)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_hashed_column_fqn_segment is typed as accepting str, but the implementation explicitly checks for None. Update the type hint to Optional[str] (and import Optional) to match the actual supported inputs and avoid static-analysis inconsistencies.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

The Python checkstyle failed.

Please run make py_format and py_format_check in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Python code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

🛡️ TRIVY SCAN RESULT 🛡️

Target: openmetadata-ingestion-base-slim:trivy (debian 12.13)

Vulnerabilities (4)

Package Vulnerability ID Severity Installed Version Fixed Version
libpng-dev CVE-2026-33416 🚨 HIGH 1.6.39-2+deb12u3 1.6.39-2+deb12u4
libpng-dev CVE-2026-33636 🚨 HIGH 1.6.39-2+deb12u3 1.6.39-2+deb12u4
libpng16-16 CVE-2026-33416 🚨 HIGH 1.6.39-2+deb12u3 1.6.39-2+deb12u4
libpng16-16 CVE-2026-33636 🚨 HIGH 1.6.39-2+deb12u3 1.6.39-2+deb12u4

🛡️ TRIVY SCAN RESULT 🛡️

Target: Java

Vulnerabilities (37)

Package Vulnerability ID Severity Installed Version Fixed Version
com.fasterxml.jackson.core:jackson-core CVE-2025-52999 🚨 HIGH 2.12.7 2.15.0
com.fasterxml.jackson.core:jackson-core CVE-2025-52999 🚨 HIGH 2.13.4 2.15.0
com.fasterxml.jackson.core:jackson-databind CVE-2022-42003 🚨 HIGH 2.12.7 2.12.7.1, 2.13.4.2
com.fasterxml.jackson.core:jackson-databind CVE-2022-42004 🚨 HIGH 2.12.7 2.12.7.1, 2.13.4
com.google.code.gson:gson CVE-2022-25647 🚨 HIGH 2.2.4 2.8.9
com.google.protobuf:protobuf-java CVE-2021-22569 🚨 HIGH 3.3.0 3.16.1, 3.18.2, 3.19.2
com.google.protobuf:protobuf-java CVE-2022-3509 🚨 HIGH 3.3.0 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2022-3510 🚨 HIGH 3.3.0 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2024-7254 🚨 HIGH 3.3.0 3.25.5, 4.27.5, 4.28.2
com.google.protobuf:protobuf-java CVE-2021-22569 🚨 HIGH 3.7.1 3.16.1, 3.18.2, 3.19.2
com.google.protobuf:protobuf-java CVE-2022-3509 🚨 HIGH 3.7.1 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2022-3510 🚨 HIGH 3.7.1 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2024-7254 🚨 HIGH 3.7.1 3.25.5, 4.27.5, 4.28.2
com.nimbusds:nimbus-jose-jwt CVE-2023-52428 🚨 HIGH 9.8.1 9.37.2
com.squareup.okhttp3:okhttp CVE-2021-0341 🚨 HIGH 3.12.12 4.9.2
commons-beanutils:commons-beanutils CVE-2025-48734 🚨 HIGH 1.9.4 1.11.0
commons-io:commons-io CVE-2024-47554 🚨 HIGH 2.8.0 2.14.0
dnsjava:dnsjava CVE-2024-25638 🚨 HIGH 2.1.7 3.6.0
io.airlift:aircompressor CVE-2025-67721 🚨 HIGH 0.27 2.0.3
io.netty:netty-codec-http CVE-2026-33870 🚨 HIGH 4.1.96.Final 4.1.132.Final, 4.2.10.Final
io.netty:netty-codec-http2 CVE-2025-55163 🚨 HIGH 4.1.96.Final 4.2.4.Final, 4.1.124.Final
io.netty:netty-codec-http2 CVE-2026-33871 🚨 HIGH 4.1.96.Final 4.1.132.Final, 4.2.11.Final
io.netty:netty-codec-http2 GHSA-xpw8-rcwv-8f8p 🚨 HIGH 4.1.96.Final 4.1.100.Final
io.netty:netty-handler CVE-2025-24970 🚨 HIGH 4.1.96.Final 4.1.118.Final
net.minidev:json-smart CVE-2021-31684 🚨 HIGH 1.3.2 1.3.3, 2.4.4
net.minidev:json-smart CVE-2023-1370 🚨 HIGH 1.3.2 2.4.9
org.apache.avro:avro CVE-2024-47561 🔥 CRITICAL 1.7.7 1.11.4
org.apache.avro:avro CVE-2023-39410 🚨 HIGH 1.7.7 1.11.3
org.apache.derby:derby CVE-2022-46337 🔥 CRITICAL 10.14.2.0 10.14.3, 10.15.2.1, 10.16.1.2, 10.17.1.0
org.apache.ivy:ivy CVE-2022-46751 🚨 HIGH 2.5.1 2.5.2
org.apache.mesos:mesos CVE-2018-1330 🚨 HIGH 1.4.3 1.6.0
org.apache.spark:spark-core_2.12 CVE-2025-54920 🚨 HIGH 3.5.6 3.5.7
org.apache.thrift:libthrift CVE-2019-0205 🚨 HIGH 0.12.0 0.13.0
org.apache.thrift:libthrift CVE-2020-13949 🚨 HIGH 0.12.0 0.14.0
org.apache.zookeeper:zookeeper CVE-2023-44981 🔥 CRITICAL 3.6.3 3.7.2, 3.8.3, 3.9.1
org.eclipse.jetty:jetty-server CVE-2024-13009 🚨 HIGH 9.4.56.v20240826 9.4.57.v20241219
org.lz4:lz4-java CVE-2025-12183 🚨 HIGH 1.8.0 1.8.1

🛡️ TRIVY SCAN RESULT 🛡️

Target: Node.js

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: Python

Vulnerabilities (13)

Package Vulnerability ID Severity Installed Version Fixed Version
apache-airflow CVE-2026-26929 🚨 HIGH 3.1.7 3.1.8
apache-airflow CVE-2026-28779 🚨 HIGH 3.1.7 3.1.8
apache-airflow CVE-2026-30911 🚨 HIGH 3.1.7 3.1.8
cryptography CVE-2026-26007 🚨 HIGH 42.0.8 46.0.5
jaraco.context CVE-2026-23949 🚨 HIGH 5.3.0 6.1.0
jaraco.context CVE-2026-23949 🚨 HIGH 6.0.1 6.1.0
pyOpenSSL CVE-2026-27459 🚨 HIGH 24.1.0 26.0.0
starlette CVE-2025-62727 🚨 HIGH 0.48.0 0.49.1
urllib3 CVE-2025-66418 🚨 HIGH 1.26.20 2.6.0
urllib3 CVE-2025-66471 🚨 HIGH 1.26.20 2.6.0
urllib3 CVE-2026-21441 🚨 HIGH 1.26.20 2.6.3
wheel CVE-2026-24049 🚨 HIGH 0.45.1 0.46.2
wheel CVE-2026-24049 🚨 HIGH 0.45.1 0.46.2

🛡️ TRIVY SCAN RESULT 🛡️

Target: /etc/ssl/private/ssl-cert-snakeoil.key

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/extended_sample_data.yaml

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/lineage.yaml

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_data.json

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_data.yaml

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_data_aut.yaml

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_usage.json

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_usage.yaml

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /ingestion/pipelines/sample_usage_aut.yaml

No Vulnerabilities Found

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

🛡️ TRIVY SCAN RESULT 🛡️

Target: openmetadata-ingestion:trivy (debian 12.13)

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: Java

Vulnerabilities (37)

Package Vulnerability ID Severity Installed Version Fixed Version
com.fasterxml.jackson.core:jackson-core CVE-2025-52999 🚨 HIGH 2.12.7 2.15.0
com.fasterxml.jackson.core:jackson-core CVE-2025-52999 🚨 HIGH 2.13.4 2.15.0
com.fasterxml.jackson.core:jackson-databind CVE-2022-42003 🚨 HIGH 2.12.7 2.12.7.1, 2.13.4.2
com.fasterxml.jackson.core:jackson-databind CVE-2022-42004 🚨 HIGH 2.12.7 2.12.7.1, 2.13.4
com.google.code.gson:gson CVE-2022-25647 🚨 HIGH 2.2.4 2.8.9
com.google.protobuf:protobuf-java CVE-2021-22569 🚨 HIGH 3.3.0 3.16.1, 3.18.2, 3.19.2
com.google.protobuf:protobuf-java CVE-2022-3509 🚨 HIGH 3.3.0 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2022-3510 🚨 HIGH 3.3.0 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2024-7254 🚨 HIGH 3.3.0 3.25.5, 4.27.5, 4.28.2
com.google.protobuf:protobuf-java CVE-2021-22569 🚨 HIGH 3.7.1 3.16.1, 3.18.2, 3.19.2
com.google.protobuf:protobuf-java CVE-2022-3509 🚨 HIGH 3.7.1 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2022-3510 🚨 HIGH 3.7.1 3.16.3, 3.19.6, 3.20.3, 3.21.7
com.google.protobuf:protobuf-java CVE-2024-7254 🚨 HIGH 3.7.1 3.25.5, 4.27.5, 4.28.2
com.nimbusds:nimbus-jose-jwt CVE-2023-52428 🚨 HIGH 9.8.1 9.37.2
com.squareup.okhttp3:okhttp CVE-2021-0341 🚨 HIGH 3.12.12 4.9.2
commons-beanutils:commons-beanutils CVE-2025-48734 🚨 HIGH 1.9.4 1.11.0
commons-io:commons-io CVE-2024-47554 🚨 HIGH 2.8.0 2.14.0
dnsjava:dnsjava CVE-2024-25638 🚨 HIGH 2.1.7 3.6.0
io.airlift:aircompressor CVE-2025-67721 🚨 HIGH 0.27 2.0.3
io.netty:netty-codec-http CVE-2026-33870 🚨 HIGH 4.1.96.Final 4.1.132.Final, 4.2.10.Final
io.netty:netty-codec-http2 CVE-2025-55163 🚨 HIGH 4.1.96.Final 4.2.4.Final, 4.1.124.Final
io.netty:netty-codec-http2 CVE-2026-33871 🚨 HIGH 4.1.96.Final 4.1.132.Final, 4.2.11.Final
io.netty:netty-codec-http2 GHSA-xpw8-rcwv-8f8p 🚨 HIGH 4.1.96.Final 4.1.100.Final
io.netty:netty-handler CVE-2025-24970 🚨 HIGH 4.1.96.Final 4.1.118.Final
net.minidev:json-smart CVE-2021-31684 🚨 HIGH 1.3.2 1.3.3, 2.4.4
net.minidev:json-smart CVE-2023-1370 🚨 HIGH 1.3.2 2.4.9
org.apache.avro:avro CVE-2024-47561 🔥 CRITICAL 1.7.7 1.11.4
org.apache.avro:avro CVE-2023-39410 🚨 HIGH 1.7.7 1.11.3
org.apache.derby:derby CVE-2022-46337 🔥 CRITICAL 10.14.2.0 10.14.3, 10.15.2.1, 10.16.1.2, 10.17.1.0
org.apache.ivy:ivy CVE-2022-46751 🚨 HIGH 2.5.1 2.5.2
org.apache.mesos:mesos CVE-2018-1330 🚨 HIGH 1.4.3 1.6.0
org.apache.spark:spark-core_2.12 CVE-2025-54920 🚨 HIGH 3.5.6 3.5.7
org.apache.thrift:libthrift CVE-2019-0205 🚨 HIGH 0.12.0 0.13.0
org.apache.thrift:libthrift CVE-2020-13949 🚨 HIGH 0.12.0 0.14.0
org.apache.zookeeper:zookeeper CVE-2023-44981 🔥 CRITICAL 3.6.3 3.7.2, 3.8.3, 3.9.1
org.eclipse.jetty:jetty-server CVE-2024-13009 🚨 HIGH 9.4.56.v20240826 9.4.57.v20241219
org.lz4:lz4-java CVE-2025-12183 🚨 HIGH 1.8.0 1.8.1

🛡️ TRIVY SCAN RESULT 🛡️

Target: Node.js

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: Python

Vulnerabilities (24)

Package Vulnerability ID Severity Installed Version Fixed Version
Authlib CVE-2026-27962 🔥 CRITICAL 1.6.6 1.6.9
Authlib CVE-2026-28490 🚨 HIGH 1.6.6 1.6.9
Authlib CVE-2026-28498 🚨 HIGH 1.6.6 1.6.9
Authlib CVE-2026-28802 🚨 HIGH 1.6.6 1.6.7
PyJWT CVE-2026-32597 🚨 HIGH 2.11.0 2.12.0
Werkzeug CVE-2024-34069 🚨 HIGH 2.2.3 3.0.3
aiohttp CVE-2025-69223 🚨 HIGH 3.12.12 3.13.3
apache-airflow CVE-2026-26929 🚨 HIGH 3.1.7 3.1.8
apache-airflow CVE-2026-28779 🚨 HIGH 3.1.7 3.1.8
apache-airflow CVE-2026-30911 🚨 HIGH 3.1.7 3.1.8
apache-airflow-providers-http CVE-2025-69219 🚨 HIGH 5.6.4 6.0.0
cryptography CVE-2026-26007 🚨 HIGH 42.0.8 46.0.5
jaraco.context CVE-2026-23949 🚨 HIGH 5.3.0 6.1.0
jaraco.context CVE-2026-23949 🚨 HIGH 6.0.1 6.1.0
protobuf CVE-2026-0994 🚨 HIGH 4.25.8 6.33.5, 5.29.6
pyOpenSSL CVE-2026-27459 🚨 HIGH 24.1.0 26.0.0
pyasn1 CVE-2026-30922 🚨 HIGH 0.6.2 0.6.3
ray CVE-2025-62593 🔥 CRITICAL 2.47.1 2.52.0
starlette CVE-2025-62727 🚨 HIGH 0.48.0 0.49.1
tornado CVE-2026-31958 🚨 HIGH 6.5.4 6.5.5
urllib3 CVE-2025-66418 🚨 HIGH 1.26.20 2.6.0
urllib3 CVE-2025-66471 🚨 HIGH 1.26.20 2.6.0
urllib3 CVE-2026-21441 🚨 HIGH 1.26.20 2.6.3
wheel CVE-2026-24049 🚨 HIGH 0.45.1 0.46.2

🛡️ TRIVY SCAN RESULT 🛡️

Target: usr/bin/docker

Vulnerabilities (2)

Package Vulnerability ID Severity Installed Version Fixed Version
stdlib CVE-2025-68121 🔥 CRITICAL v1.25.6 1.24.13, 1.25.7, 1.26.0-rc.3
stdlib CVE-2026-25679 🚨 HIGH v1.25.6 1.25.8, 1.26.1

🛡️ TRIVY SCAN RESULT 🛡️

Target: /etc/ssl/private/ssl-cert-snakeoil.key

No Vulnerabilities Found

🛡️ TRIVY SCAN RESULT 🛡️

Target: /home/airflow/openmetadata-airflow-apis/openmetadata_managed_apis.egg-info/PKG-INFO

No Vulnerabilities Found

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

Comment thread openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

The Python checkstyle failed.

Please run make py_format and py_format_check in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Python code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

Copilot AI review requested due to automatic review settings April 2, 2026 04:58
@gitar-bot
Copy link
Copy Markdown

gitar-bot bot commented Apr 2, 2026

Code Review ✅ Approved 4 resolved / 4 findings

Implements column name hashing in FQN construction with consistent UTF-8 encoding across Java and Python, adds columnsAlreadyHashed migration tracking, removes unsafe type casts, and consolidates duplicate recursive column search functions. All findings have been addressed.

✅ 4 resolved
Bug: Java hash uses platform charset; Python uses UTF-8 explicitly

📄 openmetadata-service/src/main/java/org/openmetadata/service/util/ColumnNameHash.java:39-41 📄 ingestion/src/metadata/utils/column_name_hash.py:35
The PR's core invariant is that Java and Python produce identical hashes for the same column name. However, EntityUtil.hash() calls input.getBytes() (platform default charset) while the Python implementation uses raw_column_name.encode("utf-8"). On most modern systems the default is UTF-8, but on Windows or certain JVM configurations it could be a different encoding (e.g., Cp1252). For non-ASCII column names (unicode, emoji, CJK), this would produce different hashes between Java and Python, breaking FQN resolution.

The Java ColumnNameHash.hashColumnName() delegates to EntityUtil.hash(), so the fix should be in EntityUtil.hash() or in ColumnNameHash itself.

Edge Case: Migration columnsAlreadyHashed only checks first column

📄 openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1130/MigrationUtil.java:204-214
The columnsAlreadyHashed() helper only inspects the first column in the list (line 208). If a table was partially migrated or had columns added after a previous migration attempt, the first column could be hashed while subsequent columns are not. The migration would skip the entire entity. While setColumnFQN is idempotent (always hashes from raw Column.getName()), the skip logic prevents it from running at all.

This is particularly relevant for re-runs: if the migration partially completes and is restarted, entities that were updated (first column hashed) but have new un-hashed columns would be skipped.

Quality: Unsafe cast to ColumnLevelLineageNode in LineageTable

📄 openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx:690 📄 openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx:720
The render functions cast record as unknown as ColumnLevelLineageNode (lines 690, 720), bypassing TypeScript's type safety entirely. If the record structure doesn't match (e.g., the fromColumnName/toColumnName fields aren't populated), this silently falls through to the fallback. Consider typing the column definition's render properly or using a type guard.

Quality: Duplicate recursive column search functions across two files

📄 openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx:272-286 📄 openmetadata-ui/src/main/resources/ui/src/utils/Lineage/LineageUtils.tsx:57-71
findColumnRecursive in EntityLineageUtils.tsx (lines 272-289) and findColumnInList in LineageUtils.tsx (lines 57-74) are identical in logic, parameters, and return type. Both recursively search a Column[] by fullyQualifiedName and recurse into col.children. This should be a single shared utility to avoid divergence over time.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 39 out of 39 changed files in this pull request and generated 6 comments.

Comment on lines +1326 to +1331
const columnName =
column.name ??
EntityLink.getTableColumnNameFromColumnFqn(
column.fullyQualifiedName ?? '',
false
);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findColumnByEntityLink now prefers column.name when generating the entity link, but EntityLink.getTableEntityLink does not escape/encode columnName. With column-name hashing, column entity links are expected to use the hashed FQN segment; since column.name is typically always defined and may contain reserved separators (e.g. ::, >), this will prevent matching hashed entity links and can also produce invalid/ambiguous entity links. Consider deriving the entity-link column segment from column.fullyQualifiedName (via getTableColumnNameFromColumnFqn) and, if needed for backward compatibility, compare against both raw-name and hashed-segment forms.

Copilot uses AI. Check for mistakes.
Comment on lines 466 to 474
if (!isGlossaryType && entityType === EntityType.TABLE) {
const entityLink = EntityLink.getTableEntityLink(
entityFqn ?? '',
EntityLink.getTableColumnNameFromColumnFqn(columnData?.fqn ?? '', false)
columnData?.name ??
EntityLink.getTableColumnNameFromColumnFqn(
columnData?.fqn ?? '',
false
)
);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When building the column entity link for tag suggestions, this code prefers columnData?.name. EntityLink.getTableEntityLink does not encode the column segment, and the table schema now allows :: in column names; using the raw name here can generate invalid/ambiguous entity links and will also fail to match suggestions stored using the hashed column identifier. Prefer using the column segment extracted from columnData?.fqn (hashed segment) for the entity link, and keep the readable name only for display.

Copilot uses AI. Check for mistakes.
Comment on lines 42 to 49
const entityLink = useMemo(
() =>
entityType === EntityType.TABLE
? EntityLink.getTableEntityLink(
entityFqn,
EntityLink.getTableColumnNameFromColumnFqn(columnData.fqn, false)
columnData.record?.name ??
EntityLink.getTableColumnNameFromColumnFqn(columnData.fqn, false)
)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EntityLink.getTableEntityLink does not escape/encode the column segment. Preferring columnData.record?.name here can produce invalid/ambiguous entity links now that column names may legally contain :: and other reserved characters, and it can prevent matching against stored entity links that use the hashed column identifier. Prefer using the column segment from columnData.fqn (i.e., getTableColumnNameFromColumnFqn(columnData.fqn, false)) when constructing the entity link.

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +82
const findColumnNameByFqn = (
columnFqn: string,
entityData: NodeData['entity']
): string | undefined => {
const columns = (entityData as unknown as { columns?: Column[] }).columns;
if (!columns) {
return undefined;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findColumnNameByFqn relies on entityData as unknown as { columns?: Column[] } because NodeData['entity'] is typed as EntityReference, but LineageProvider populates NodeData.entity with full LineageNodeType objects (including columns). Consider tightening the NodeData type to reflect the actual shape (e.g., LineageNodeType | EntityReference) and adding a type guard for columns to avoid unsafe casts and make this helper safer to evolve.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +58
public static boolean isHashedColumnFQNSegment(String segment) {
return segment != null && segment.startsWith(HASH_PREFIX) && segment.length() == HASH_LENGTH;
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isHashedColumnFQNSegment only checks prefix + length. A real column segment like md5_<32 chars> would be misclassified as already-hashed, which can break validation/migration logic. Consider also validating that the suffix is 32 hex characters (e.g., [0-9a-fA-F]{32}) to avoid accidental collisions.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to 75
# Now populate the dictionary with the imported classes.
# Note: ColumnName, ColumnProfile, and CustomColumnName entries have been
# removed — column FQN segments are now hashed, making reserved-keyword
# encoding unnecessary for column names. Table-level transforms are kept
# for backward compatibility with existing encoded data in the database.
TRANSFORMABLE_ENTITIES.update(
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indicates reserved-keyword encoding for column names was removed, but BaseModel.parse_name still applies replace_separators recursively to CreateTableRequest (and other Create* models), which will continue encoding column name.root values containing ::, > or ". With the new hashing-based FQN segment, this would cause the server and client to hash different inputs (encoded vs raw), breaking cross-language FQN/entity-link consistency. To align with the new approach, update the name-transform logic to skip column-name encoding for create/store models (or otherwise ensure both Java and Python hash the same normalized form).

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 2, 2026

Quality Gate Failed Quality Gate failed for 'open-metadata-ingestion'

Failed conditions
E Security Review Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

🔴 Playwright Results — 50 failure(s), 21 flaky

✅ 3360 passed · ❌ 50 failed · 🟡 21 flaky · ⏭️ 259 skipped

Shard Passed Failed Flaky Skipped
🔴 Shard 1 448 2 1 6
🔴 Shard 2 611 4 4 32
🔴 Shard 3 590 24 6 27
🔴 Shard 4 608 11 5 47
🔴 Shard 5 579 7 1 67
🔴 Shard 6 524 2 4 80

Genuine Failures (failed on all attempts)

Features/DescriptionSuggestion.spec.ts › View, Close, Reject and Accept the Suggestions (shard 1)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveCount�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator:  getByTestId('suggested-SuggestDescription-card')
Expected: �[32m9�[39m
Received: �[31m5�[39m
Timeout:  15000ms

Call log:
�[2m  - Expect "toHaveCount" with timeout 15000ms�[22m
�[2m  - waiting for getByTestId('suggested-SuggestDescription-card')�[22m
�[2m    18 × locator resolved to 5 elements�[22m
�[2m       - unexpected value "5"�[22m

Features/MutuallyExclusiveColumnTags.spec.ts › Should show error toast when adding mutually exclusive tags to column (shard 1)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/ColumnBulkOperations.spec.ts › should update display name and propagate to all occurrences (shard 2)
Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoContain�[2m(�[22m�[32mexpected�[39m�[2m) // indexOf�[22m

Expected substring: �[32m"user_idec3c554d"�[39m
Received string:    �[31m"pw-database-service-2c2987e7.pw-database-29fd0fec.pw-database-schema-4091937f.pw-table-4fe3e832-a431-4f6b-b4c7-bd81fec59782.md5_6061262235b4c9cf2e0a8647b552910f"�[39m
Features/CustomMetric.spec.ts › Column custom metric (shard 2)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: getByTestId('columnCustomMetric-2c61e52e-title')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByTestId('columnCustomMetric-2c61e52e-title')�[22m

Features/Dashboards.spec.ts › expand / collapse should not appear after updating nested fields for dashboardDataModels (shard 2)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/Glossary/GlossaryMutualExclusivity.spec.ts › ME-T02: Apply ME term to table column via detail panel (shard 2)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-nested-db-svc-483fcd43.pw-nested-db-483fcd43.pw-nested-schema-483fcd43.pw-nested-table-483fcd43.details.name-c97e8462"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-nested-db-svc-483fcd43.pw-nested-db-483fcd43.pw-nested-schema-483fcd43.pw-nested-table-483fcd43.details.name-c97e8462"] [data-testid="expand-icon"]')�[22m

Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-nested-dash-svc-8d8641e2.model.pw-nested-dm-8d8641e2.user_details"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-nested-dash-svc-8d8641e2.model.pw-nested-dm-8d8641e2.user_details"] [data-testid="expand-icon"]')�[22m

Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-worksheet-service-379cced9.pw-spreadsheet-26e9f763.pw-worksheet-ded608a7.details"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-worksheet-service-379cced9.pw-spreadsheet-26e9f763.pw-worksheet-ded608a7.details"] [data-testid="expand-icon"]')�[22m

Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-directory-service-0531c47d.pw-directory-7d3c9393.pw-file-3cc71cda.details"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-directory-service-0531c47d.pw-directory-7d3c9393.pw-file-3cc71cda.details"] [data-testid="expand-icon"]')�[22m

Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names in Version History (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-nested-db-svc-50cc3e27.pw-nested-db-50cc3e27.pw-nested-schema-50cc3e27.pw-nested-table-50cc3e27.details.name-080f53f0"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-nested-db-svc-50cc3e27.pw-nested-db-50cc3e27.pw-nested-schema-50cc3e27.pw-nested-table-50cc3e27.details.name-080f53f0"] [data-testid="expand-icon"]')�[22m

Features/NestedColumnsExpandCollapse.spec.ts › should not duplicate rows when expanding and collapsing nested columns with same names in Profiler Tab (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-nested-db-svc-125bc58c.pw-nested-db-125bc58c.pw-nested-schema-125bc58c.pw-nested-table-125bc58c.details"] [data-testid="expand-icon"]')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-nested-db-svc-125bc58c.pw-nested-db-125bc58c.pw-nested-schema-125bc58c.pw-nested-table-125bc58c.details"] [data-testid="expand-icon"]')�[22m

Features/Table.spec.ts › expand collapse should only visible for nested columns (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: locator('[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.shipping_address"]').getByTestId('expand-icon')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.shipping_address"]').getByTestId('expand-icon')�[22m

Features/Table.spec.ts › expand / collapse should not appear after updating nested fields table (shard 3)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/Table.spec.ts › Glossary term should be consistent for search (shard 3)
Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBeGreaterThan�[2m(�[22m�[32mexpected�[39m�[2m)�[22m

Expected: > �[32m0�[39m
Received:   �[31m0�[39m

Call Log:
- Test timeout of 60000ms exceeded
Features/Table.spec.ts › Tags term should be consistent for search (shard 3)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/Table.spec.ts › Search for column, copy link, and verify side panel behavior (shard 3)
�[31mTest timeout of 180000ms exceeded.�[39m
Features/TagsSuggestion.spec.ts › View, Close, Reject and Accept the Suggestions (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveCount�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator:  getByTestId('suggested-SuggestTagLabel-card')
Expected: �[32m9�[39m
Received: �[31m5�[39m
Timeout:  15000ms

Call log:
�[2m  - Expect "toHaveCount" with timeout 15000ms�[22m
�[2m  - waiting for getByTestId('suggested-SuggestTagLabel-card')�[22m
�[2m    19 × locator resolved to 5 elements�[22m
�[2m       - unexpected value "5"�[22m

Features/TagsSuggestion.spec.ts › Reject All Suggestions (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).not.�[22mtoContainText�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator: locator('[data-row-key*=shop_id240845ad] [data-testid="tags-container"]')
Expected substring: not �[32m"Personal"�[39m
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "not toContainText" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key*=shop_id240845ad] [data-testid="tags-container"]')�[22m

Flow/FrequentlyJoined.spec.ts › should display frequently joined columns (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoContainText�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator: locator('[data-row-key="sample_data.ecommerce_db.shopify.fact_sale.customer_id"]')
Expected substring: �[32m"Frequently Joined Columns:ecommerce_db.shopify.dim_customer.customer_id"�[39m
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toContainText" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="sample_data.ecommerce_db.shopify.fact_sale.customer_id"]')�[22m

Flow/NestedChildrenUpdates.spec.ts › should update nested column description immediately without page refresh (shard 3)
Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m

Expected: �[32m200�[39m
Received: �[31m404�[39m
Flow/NestedChildrenUpdates.spec.ts › should add and remove tags to nested column immediately without refresh (shard 3)
�[31mTest timeout of 60000ms exceeded.�[39m
Flow/NestedChildrenUpdates.spec.ts › should update nested column displayName immediately without refresh (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveText�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-dashboard-service-e3f74814.model.pw-dashboard-data-model-83c31aa9.md5_6f269b41771ef5242ca216afeb4bc10e.md5_b068931cc450442b63f5b3d276ea4297"]').getByTestId('column-display-name')
Expected: �[32m"Customer Full Name"�[39m
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toHaveText" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-dashboard-service-e3f74814.model.pw-dashboard-data-model-83c31aa9.md5_6f269b41771ef5242ca216afeb4bc10e.md5_b068931cc450442b63f5b3d276ea4297"]').getByTestId('column-display-name')�[22m

Flow/NestedChildrenUpdates.spec.ts › should update nested column description immediately without page refresh (shard 3)
Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m

Expected: �[32m200�[39m
Received: �[31m404�[39m
Flow/NestedChildrenUpdates.spec.ts › should add and remove tags to nested column immediately without refresh (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).not.�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator:  getByTestId('saveAssociatedTag')
Expected: not visible
Received: visible
Timeout:  15000ms

Call log:
�[2m  - Expect "not toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByTestId('saveAssociatedTag')�[22m
�[2m    19 × locator resolved to <button type="submit" data-testid="saveAssociatedTag" ant-click-animating-without-extra-node="false" class="ant-btn ant-btn-default ant-btn-sm update-btn">…</button>�[22m
�[2m       - unexpected value "visible"�[22m

Flow/NestedChildrenUpdates.spec.ts › should update nested column displayName immediately without refresh (shard 3)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveText�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

Locator: locator('[data-row-key="pw-dashboard-service-018daa69.model.pw-dashboard-data-model-82202e81.md5_6f269b41771ef5242ca216afeb4bc10e.md5_b068931cc450442b63f5b3d276ea4297.md5_2a034e9d9e2601c21191cca53760eaaf"]').getByTestId('column-display-name')
Expected: �[32m"Street Full Name"�[39m
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toHaveText" with timeout 15000ms�[22m
�[2m  - waiting for locator('[data-row-key="pw-dashboard-service-018daa69.model.pw-dashboard-data-model-82202e81.md5_6f269b41771ef5242ca216afeb4bc10e.md5_b068931cc450442b63f5b3d276ea4297.md5_2a034e9d9e2601c21191cca53760eaaf"]').getByTestId('column-display-name')�[22m

Flow/NestedChildrenUpdates.spec.ts › should update nested column description immediately without page refresh (shard 3)
�[31mTest timeout of 60000ms exceeded while running "beforeEach" hook.�[39m
Flow/NestedChildrenUpdates.spec.ts › should add and remove tags to nested column immediately without refresh (shard 3)
�[31mTest timeout of 60000ms exceeded while running "beforeEach" hook.�[39m
Flow/NestedChildrenUpdates.spec.ts › should update nested column description immediately without page refresh (shard 3)
�[31mTest timeout of 60000ms exceeded while running "beforeEach" hook.�[39m
Flow/NestedChildrenUpdates.spec.ts › should add and remove tags to nested column immediately without refresh (shard 3)
�[31mTest timeout of 60000ms exceeded while running "beforeEach" hook.�[39m

... and 20 more failures

🟡 21 flaky test(s) (passed on retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/DataProductRenameConsolidation.spec.ts › Multiple rename + update cycles - assets should be preserved (shard 2, 1 retry)
  • Features/DataQuality/BundleSuiteBulkOperations.spec.ts › Bulk selection operations (shard 2, 1 retry)
  • Features/DataQuality/ColumnLevelTests.spec.ts › Column Values Sum To Be Between (shard 2, 1 retry)
  • Features/Glossary/GlossaryTermDetails.spec.ts › should verify bidirectional related term link (shard 3, 1 retry)
  • Features/IncidentManager.spec.ts › Complete Incident lifecycle with table owner (shard 3, 2 retries)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Features/Table.spec.ts › should persist current page (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter (shard 3, 1 retry)
  • Flow/PersonaFlow.spec.ts › Set default persona for team should work properly (shard 3, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate Description Rule Is_Set (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Data Product announcement create, edit & delete (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with deeply nested subdomains (3+ levels) verifies FQN propagation (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Multiple consecutive domain renames preserve all associations (shard 4, 1 retry)
  • Pages/EntityDataConsumer.spec.ts › Glossary Term Add, Update and Remove (shard 5, 1 retry)
  • Pages/Glossary.spec.ts › Column dropdown drag-and-drop functionality for Glossary Terms table (shard 6, 2 retries)
  • Pages/ODCSImportExport.spec.ts › Multi-object ODCS contract - object selector shows all schema objects (shard 6, 1 retry)
  • Pages/ProfilerConfigurationPage.spec.ts › Non admin user (shard 6, 1 retry)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@mohittilala mohittilala moved this to Validation in Shipping Apr 16, 2026
@mohittilala mohittilala removed the status in Shipping Apr 16, 2026
@mohittilala mohittilala self-assigned this Apr 16, 2026
@mohittilala mohittilala moved this to Validation in Shipping Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ingestion safe to test Add this label to run secure Github workflows on PRs

Projects

Status: Validation

Development

Successfully merging this pull request may close these issues.

2 participants