Skip to content

Global AI catalog partitions are absent from the search/query index — Providers/Models/Agents/Skills catalogs render empty although the nodes exist #354

Description

@sierragolflima

Summary

On affected deployed instances, the global AI catalog partitions (Provider, Model, Agent, Skill, Harness) are materialized but missing from the search/query index. Every index-based access (search, children-listing, the catalog layout areas) returns empty, while authoritative exact-path reads succeed. The AI-menu catalog areas are index-driven, so they render empty.

How to reproduce

Precondition: a deployed instance that has at least one global catalog node (e.g. a Provider/<name> node exists — confirm with step 1).

  1. Exact-path read (authoritative): get @Provider/Anthropic → returns the ModelProvider node. ✅ node exists.
  2. Children listing (index-based): get @Provider/* → [] ❌ (should list Provider/Anthropic).
  3. Search (index-based):
    • search nodeType:ModelProvider → 0 ❌
    • search namespace:Provider scope:descendants nodeType:ModelProvider → 0 ❌
  4. UI: open the top-bar AI menu → Providers (and Models / Agents / Skills) → the catalog renders empty.

Expected: steps 2–4 return / show the existing node(s).
Actual: steps 2–4 return empty, while step 1 proves the node exists.

Same pattern for the other roots: get @Agent/*, @Skill/*, @Harness/* → []; search nodeType:Agent/Skill return only space-partition nodes, never the global catalog.

Impact

  • All four AI-menu catalogs (Providers / Models / Agents / Skills) render empty.
  • The BYO-API-key UI (AI menu → Providers → create/edit a personal provider) is unusable.
  • The harness picker (namespace:Harness nodeType:Harness) is empty ⇒ /harness can't switch to a CLI harness ⇒ the /login Connect flow can't be reached there (see Document how to enable per-user Claude Code Connect (Features__Ai__Clis__ClaudeCode) and its prerequisites #324).
  • The "empty picker ⇒ no nodes exist" diagnostic in ModelProviderSetup.md (line 231) is misleading — the nodes exist, they're just unindexed.

Why it's an index-registration gap, not a catalog-UI bug

The catalog renders whatever search returns; the search index simply doesn't include these partitions on the affected instance. Evidence it's index-scoped: on a separate instance the searchable_schemas registry (the schemas the search unions over) contains provider/agent/skill/model/harness; on the affected instance, index queries return empty for exactly those partitions while exact-path get works. So the fix belongs in the searchable-schemas sync/registration, not the catalog rendering.

Likely cause / fix

SyncSearchableSchemasAsync is meant to register the catalog partitions as searchable on each run ("a real catalog wrongly missing is re-added on the next sync"). On affected instances these partitions are absent from the search read-model. Ensure the reconcile registers + indexes the global catalog partitions and self-heals instances already in this state; add a repair path.

References

  • src/MeshWeaver.AI/AiCatalogLayoutAreas.cs (index-driven catalogs)
  • SyncSearchableSchemasAsync / searchable_schemas
  • ThreadComposer harness pick (namespace:Harness nodeType:Harness)

🤖 Generated with Claude Code

Activity

  1. rbuergi commented on Jul 18, 2026

    @rbuergi
    Contributor

    RCA (verified against source)

    The AI catalog partitions (Provider/Model/Agent/Skill/Harness) only enter the search/query index when they exist as real Postgres partition schemas in public.searchable_schemas. A PG schema is created only on the dbSynced path (StaticRepoImporter → EnsurePartitionProvisioned); when a deployment doesn't dbSync them, each type registers an in-memory StaticNodePartitionStorageProvider that creates no PG schema. Result: exact-path get @Provider/Anthropic works (in-memory provider), but nodeType:ModelProvider (pathless fan-out over searchable_schemas) and namespace:Provider scope:descendants return 0 — "materialized but unindexed."

    The config-alias/allow-list drift that caused this was largely fixed by PR #407 (merged 2026-07-10, 3 days after this issue): the AiContentSources.ContentPartitions bundle + the Overlaps→UnionWith expansion + the Helm default now listing Provider.

    Residual (still live, actionable): there is no boot-time self-heal or assertion that a served AI catalog partition actually provisioned into a PG schema and registered in searchable_schemas. An instance whose StaticRepoSync is empty/non-overlapping (or whose boot import failed) silently runs the catalogs in-memory forever. Implementing a boot self-heal/assert (verify each AiContentSources.ContentPartitions member has a PG schema + force a searchable_schemas re-sync; surface a startup-failure notification otherwise) — PR incoming. Testable via PG Testcontainers (CrossPartitionSearchTests).

  2. added a commit that references this issue on Jul 18, 2026
  3. rbuergi commented on Jul 18, 2026

    @rbuergi
    Contributor

    Residual fixed and merged: #524 adds a boot-time self-heal/assert that every served AI catalog partition is provisioned into a PG schema and registered in searchable_schemas (forcing a one-time rebuild + a startup-failure notification if one didn't land). The config-drift half was already fixed by #407. Closing.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions