Skip to content

fix: search anywhere crashes on SchemaNode UUID lookup#8942

Open
BeArchiTek wants to merge 16 commits intostablefrom
fix/search-anywhere-schema-node-crash
Open

fix: search anywhere crashes on SchemaNode UUID lookup#8942
BeArchiTek wants to merge 16 commits intostablefrom
fix/search-anywhere-schema-node-crash

Conversation

@BeArchiTek
Copy link
Copy Markdown
Contributor

@BeArchiTek BeArchiTek commented Apr 16, 2026

Summary

  • Backend: The UUID search path in InfrahubSearchAnywhere returned any node regardless of namespace. When a user searched for a SchemaNode UUID (e.g. from a proposed change validation error), the backend returned kind: "SchemaNode" which the frontend couldn't resolve, causing a crash. Added namespace filtering to exclude Schema and Internal nodes — consistent with the string search path that already filters by CoreNode/CoreGroup.
  • Frontend: useGetObject was called with a null-asserted schema (schema!) before the null check, crashing in getObjectQueryOptions when accessing .kind on null. Split NodesOptions into a schema-resolving wrapper and a details component so useGetObject is only called when schema is guaranteed non-null.

Test plan

  • Backend component test: test_search_anywhere_by_uuid_excludes_internal_nodes — creates nodes with Internal and Schema namespaces, verifies UUID search returns 0 results for both
  • Frontend unit test: search-nodes.test.tsx — verifies NodesOptions does not call useGetObject when useSchema returns null
  • Manual: search for a SchemaNode UUID in the search bar — should return no results instead of crashing

Summary by cubic

Fixes Search Anywhere crashing on Schema/Internal UUIDs by returning those nodes with a display_label and a target_kind, then rendering a simple result that links to the actual schema entry. Links preserve branch/datetime query params; text search and regular nodes are unchanged.

  • New Features

    • GraphQL: Added nullable display_label and target_kind to search Node; UUID search now returns Schema/Internal nodes with both fields.
    • Frontend: Requests display_label/target_kind and uses target_kind for the link and kind badge in a simplified row (no extra fetch).
    • Tests: Backend covers UUID inclusion and display_label; text search still excludes Schema/Internal. Frontend tests verify target_kind routing, label fallback, and regular node behavior.
  • Bug Fixes

    • Split NodesOptions into a schema resolver and a details component so useGetObject is never called with a null schema, preventing the crash.
    • Schema link now uses constructPath to keep existing branch/datetime query params.
    • Regenerated GraphQL schema and updated Node type to include the new fields consistently.
    • Restored Betterer entry for artifacts/types.ts to keep CI passing.

Written for commit 5cf67b6. Summary will update on new commits.

The UUID search path in InfrahubSearchAnywhere returned any node
regardless of namespace, including internal Schema/Internal nodes.
The frontend then crashed with "Cannot read properties of null
(reading 'kind')" because SchemaNode is not in the frontend schema
registry.

Backend: filter UUID search results by namespace, excluding Schema
and Internal nodes — consistent with the string search path.

Frontend: split NodesOptions into a schema-resolving wrapper and a
details component to prevent useGetObject from being called with a
null schema.
@BeArchiTek BeArchiTek requested review from a team as code owners April 16, 2026 10:30
@github-actions github-actions Bot added group/backend Issue related to the backend (API Server, Git Agent) group/frontend Issue related to the frontend (React) labels Apr 16, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/tests/component/graphql/queries/test_search.py">

<violation number="1" location="backend/tests/component/graphql/queries/test_search.py:79">
P1: Custom agent: **Flag ad-hoc reproducer tests committed to CI (unmarked/flaky reproducer code)**

This is an unmarked reproducer test; mark it skip/xfail or gate it behind an explicit opt-in before committing it to CI.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread backend/tests/component/graphql/queries/test_search.py Outdated
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 16, 2026

Merging this PR will not alter performance

✅ 12 untouched benchmarks


Comparing fix/search-anywhere-schema-node-crash (1ee5b40) with stable (c5999d5)

Open in CodSpeed

BeArchiTek and others added 9 commits April 16, 2026 15:25
Phase 0 research + Phase 1 design artifacts:
- research.md, data-model.md, quickstart.md, contracts/

Co-Authored-By: Claude Opus 4.6 <[email protected]>
24 tasks across 6 phases, organized by user story.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…odes

UUID search now returns Schema and Internal namespace nodes with a
human-readable display_label. The frontend renders a simplified result
linking to /schema?kind={kind} instead of crashing on unknown schemas.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@github-actions github-actions Bot added the type/spec A specification for an upcoming change to the project label Apr 16, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 17 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/app/src/entities/navigation/ui/search-anywhere/search-nodes.tsx">

<violation number="1" location="frontend/app/src/entities/navigation/ui/search-anywhere/search-nodes.tsx:82">
P2: Use `constructPath` for the schema fallback URL instead of a manual query string. The current URL drops preserved query params (branch/datetime) and can mis-handle unencoded kinds.</violation>
</file>

<file name="dev/specs/005-search-display-label/quickstart.md">

<violation number="1" location="dev/specs/005-search-display-label/quickstart.md:9">
P1: The quickstart instructions reverse the intended UUID-search filtering behavior, which can reintroduce the Schema/Internal result-path crash/regression.</violation>
</file>

<file name="backend/tests/component/graphql/queries/test_search.py">

<violation number="1" location="backend/tests/component/graphql/queries/test_search.py:117">
P2: This UUID regression test now expects Schema/Internal nodes to be returned, which is the opposite of the crash fix. It should assert zero results so the test actually guards the exclusion behavior.</violation>
</file>

<file name="backend/infrahub/graphql/queries/search.py">

<violation number="1" location="backend/infrahub/graphql/queries/search.py:120">
P1: UUID search no longer filters out `Schema`/`Internal` nodes, so internal objects can be returned where search is expected to exclude them.</violation>
</file>

<file name="dev/specs/005-search-display-label/tasks.md">

<violation number="1" location="dev/specs/005-search-display-label/tasks.md:34">
P1: This task reverses the intended UUID filtering behavior by telling implementers to remove the Schema/Internal filter.</violation>

<violation number="2" location="dev/specs/005-search-display-label/tasks.md:36">
P1: This test task specifies assertions opposite to the intended UUID behavior, likely locking in a regression.</violation>
</file>

<file name="dev/specs/005-search-display-label/contracts/search-graphql.md">

<violation number="1" location="dev/specs/005-search-display-label/contracts/search-graphql.md:48">
P2: The UUID behavior table contradicts the implemented fix by saying Schema/Internal UUID searches return results; the contract should document zero results for those namespaces.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread dev/specs/005-search-display-label/quickstart.md
Comment thread backend/infrahub/graphql/queries/search.py Outdated
Comment thread dev/specs/005-search-display-label/tasks.md
Comment thread dev/specs/005-search-display-label/tasks.md
Comment thread frontend/app/src/entities/navigation/ui/search-anywhere/search-nodes.tsx Outdated
Comment thread backend/tests/component/graphql/queries/test_search.py
Comment thread dev/specs/005-search-display-label/contracts/search-graphql.md
BeArchiTek and others added 3 commits April 16, 2026 21:51
The entry was dropped during earlier betterer updates but CI needs it
since the generated types.ts is not committed to git.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/app/.betterer.results">

<violation number="1">
P2: This change introduces a new TypeScript error into the Betterer baseline, which masks a real compile-time issue instead of resolving it.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread frontend/app/.betterer.results
BeArchiTek and others added 2 commits April 17, 2026 10:40
SchemaNode records have kind="SchemaNode" but describe another schema
(e.g. CoreGroupAction). The frontend was using node.kind for the URL,
navigating to the generic SchemaNode page instead of the described
schema's page.

Backend now exposes target_kind (composed from namespace + name
attributes) for Schema records. Frontend uses target_kind for both
the URL and the kind badge in the simplified view.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented Apr 17, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

node_data = result.data["InfrahubSearchAnywhere"]["edges"][0]["node"]
assert node_data["id"] == internal_node.id
assert node_data["kind"] == "InternalWidget"
assert node_data["display_label"] is not None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the test should be able to assert what the display label is

node_data = result.data["InfrahubSearchAnywhere"]["edges"][0]["node"]
assert node_data["display_label"] is not None
assert isinstance(node_data["display_label"], str)
assert len(node_data["display_label"]) > 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

samesies

assert result.errors is None
assert result.data
assert result.data["InfrahubSearchAnywhere"]["count"] == 0
assert result.data["InfrahubSearchAnywhere"]["edges"] == []
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

doesn't seem to be introduced in this PR, but it seems like an anti-pattern that Internal schema objects are only included in the search results if the search term is the ID of the internal object. I would expect searching for the name of findable-widget here to return it

Comment on lines +29 to +31
"For Schema records (SchemaNode/SchemaGeneric), the kind of the schema they "
"describe so clients can link to that schema's page instead of the generic "
"SchemaNode/SchemaGeneric page."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this description of a GraphQL field shouldn't describe how the client works. maybe something like
"If kind is SchemaNode/SchemaGeneric, target_kind is set to the name of the schema (eg BuiltinTag)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/backend Issue related to the backend (API Server, Git Agent) group/frontend Issue related to the frontend (React) type/spec A specification for an upcoming change to the project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants