Skip to content

[console] AppContent's post-publish readiness re-check is skipped for the second of two consecutive missing apps #4522

Description

@yinlianghui

Found while implementing #4252 (PR #4521); not fixed there — out of that card's scope, and it predates it.

What

packages/app-shell/src/console/AppContent.tsx holds the post-publish readiness re-check in missingRecheck: 'idle' | 'checking' | 'done'. It is reset to 'idle' on exactly one condition — requestedAppMissing going false:

useEffect(() => {
  if (!requestedAppMissing) {
    if (missingRecheck !== 'idle') setMissingRecheck('idle');
    return;
  }
  if (missingRecheck === 'idle' && !metadataLoading && !previewDrafts) {
    setMissingRecheck('checking');
    Promise.resolve(refreshMetadata()).finally(() => setMissingRecheck('done'));
  }
}, [requestedAppMissing, metadataLoading, previewDrafts, missingRecheck, refreshMetadata]);

Navigating from one missing app to another missing app never satisfies that condition: requestedAppMissing is true before the transition and true after it, so missingRecheck stays 'done' and the second app gets no re-check. The state is a flag about "a re-check has run", not about which app it ran for.

Why it matters

The re-check exists because "the registry can lag a beat behind a publish" — it is what makes a just-built app resolve on its own instead of flashing "App not available". An app reached second in a session (launcher → typo'd URL → the real, freshly-published app; or two attempts in a row while a build lands) does not get that grace, and shows the not-available screen with no refresh behind it. Retry still works, so the user has a way out — which is why this reads as low severity rather than a strand.

Severity note

Graded observation-class at filing time (finding, no pm:queue): the failure needs two consecutive missing apps in one mount, and the visible cost is one skipped refresh, not a wrong screen. Grade it in triage rather than trusting that line — severity judged at filing time is unreliable in both directions in this repo's history.

Related but distinct

PR #4521 hit the same shape one state over and had to fix it there, because the consequence differed: the access verdict it introduces would have shown the wrong screen (the first app's authorization denial over the second app's absence), rather than merely skipping work. That one is keyed to the app it describes and pinned by a test; missingRecheck was deliberately left as-is so the fix stayed inside #4252's surface.

Not to be confused with #4486 (MetadataProvider cache keyed by type, not org) — different layer, different cache.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions