Skip to content

fix: surface failed component list loads in expose components form - #106

Open
0717lee wants to merge 3 commits into
contextforge-org:mainfrom
0717lee:fix/expose-components-error-state
Open

fix: surface failed component list loads in expose components form#106
0717lee wants to merge 3 commits into
contextforge-org:mainfrom
0717lee:fix/expose-components-error-state

Conversation

@0717lee

@0717lee 0717lee commented Sep 5, 2026

Copy link
Copy Markdown

Closes #6549

Summary

In the expose step, the three component lists are loaded with useQuery but only data, isLoading, and refetch are destructured — error is never read. A failed /tools, /resources, or /prompts request therefore renders identically to a successful empty one: the section shows "0 tools" / "0 resources" / "0 prompt templates" and invites pressing "Expose components" on what looks like a server offering nothing.

  • Each section now reads its own query error. When a load fails, the count line shows "Failed to load …" in the app-wide error tone (via STATUS_TONE_CLASS) instead of a zero count, and the section renders an error InlineNotification with the API error message and a Retry action that refetches just that list.
  • Sections whose own request succeeded keep showing their real counts, including legitimate zeros — a connected MCP server that exposes no tools, resources, or prompts is not an error, and must keep rendering as it does today.

Unit tests cover the failed/empty distinction, per-section independence (some sections fail while others keep their counts), and recovery through Retry.

A failed /tools, /resources, or /prompts request rendered identically
to a successful empty one: the section showed a zero count with no
error. Read the useQuery error per section, show the count line as
"Failed to load ..." with an error notification and a retry action,
and keep real counts (including legitimate zeros) for sections whose
request succeeded.

Signed-off-by: Li Fengmin <2080291162@qq.com>
@marekdano
marekdano requested a review from a-effort September 7, 2026 09:21

@gcgoncalves gcgoncalves left a comment

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.

Thanks @0717lee for this PR, the error handling is a nice improvement to the form. There are a couple suggestions for the proposed implementation:

First, it'd be nice to improve i18n (see comment below). Also, when a user clicks Retry for the tools section, toolsLoading becomes true. Then, the entire form is replaced by a spinner, including the resources and prompts sections, that are still valid.

My suggestion is using the individual loading states to add guards to each section:

  {toolsLoading ? (
    <span className="text-sm text-muted-foreground">
      {intl.formatMessage({ id: "common.loading" })}
    </span>
  ) : toolsError ? (
    intl.formatMessage({ id: "gateways.exposeComponents.error.tools" })
  ) : (
    intl.formatMessage({ id: "gateways.card.toolCount" }, { count: toolCount })
  )}

message={
toolsError.message
? `Failed to load tools: ${toolsError.message}`
: "Failed to load tools"

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.

All the "Failed to load tools" instances are not internationalised. Please add the appropriate keys to the i18n files and invoke them here and on line 365.

- Add gateways.exposeComponents.error.{tools,resources,prompts}(WithDetail)
  and exposeComponents.promptCount keys to en-US, pt-BR, and es-ES; reuse
  the existing gateways.card.*Count keys for tools and resources.
- Replace the form-level spinner on refetch with per-section count-row
  states (loading / error / count); the full-form spinner now only covers
  the initial load before any section has resolved, so retrying one failed
  section no longer unmounts the healthy ones.

Signed-off-by: Li Fengmin <2080291162@qq.com>
@0717lee

0717lee commented Sep 7, 2026

Copy link
Copy Markdown
Author

Thanks for the review @gcgoncalves — both points addressed in 79cdee2:

  1. i18n: the load-failure strings are now message keys — gateways.exposeComponents.error.{tools,resources,prompts} plus *WithDetail variants for the inline notifications, landed in en-US, pt-BR, and es-ES. The section counts reuse the existing gateways.card.toolCount/resourceCount keys; prompts got a new gateways.exposeComponents.promptCount key to keep the current "prompt template(s)" wording.

  2. Per-section loading: each section's count row now renders loading → common.loading / error → error key / otherwise count, and the form-level spinner only covers the initial load (before any section has resolved). Retrying tools no longer replaces the still-valid resources/prompts sections with a spinner.

Added a regression test ("should keep healthy sections mounted while a failed section retries") that pins this: during a hanging tools retry, the other sections stay mounted and no form-level spinner appears. Full vitest (3324 passed), tsc -b, and the locale parity checks are green.

: intl.formatMessage({ id: "gateways.exposeComponents.error.tools" })
}
action={{
label: "Retry",

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.

i18n this label as well, please. Key: common.button.retry

Signed-off-by: Li Fengmin <2080291162@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][UI-REWRITE]: Expose components step shows 0 counts when the component lists fail to load

2 participants