Skip to content

finding(app-shell): fetchFullPackage never reads res.ok, so a failed package lookup opens the management sheet on a null package - silently #7881

Description

@claude

Observation

Found while fixing objectui#7821 (the onManageChanged false-deletion eviction), in the
same component and one callback above it. Deliberately not fixed there: that card is
scoped to the deletion inference, and this is a different swallowed failure with a
different wrong outcome.

fetchFullPackage in packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx
(origin/main 384715bb1, the PackageSwitcher helper that backs openManage):

const fetchFullPackage = React.useCallback(async (id: string) => {
  const res = await fetch('/api/v1/packages', {
    credentials: 'include',
    headers: { Accept: 'application/json' },
    cache: 'no-store',
  });
  const data = (await res.json()) as unknown;
  const root = (data as { data?: unknown })?.data ?? data;
  const list = (Array.isArray(root) ? root : ((root as { packages?: unknown[] })?.packages ?? [])) as ...;
  return list.find((p) => (p?.manifest?.id ?? p?.id) === id) ?? null;
}, []);

res.ok is never read. The endpoint answers an error the way the rest of this platform
does — a JSON envelope with success: false and an error object — so on a 4xx/5xx
that envelope parses cleanly: root is the error object, it is not an array and has
no packages, so list is [] and the function returns null. Nothing throws, so
openManage's catch (which does toast, formatMetadataError) never runs:

setManage(await fetchFullPackage(id));   // null
setManageOpen(true);                     // …and the sheet opens anyway

Net effect: an author clicking "Package info & settings" during an outage gets the
management sheet opened on a null package — no toast, no error, no explanation —
instead of being told the lookup failed. Same defect family as objectui#7368 and
objectui#7821, third variant: not a lost toast and not an inverted decision, but a
failure laundered into a successful-looking empty result.

Two adjacent observations on the same function, offered as context rather than as
separate claims:

  • It reaches /api/v1/packages with a raw fetch, which AGENTS.md §7 bans in
    components in favour of @objectstack/client; the sibling fetchPackages in
    ./packages-io.ts already goes through the sanctioned path and already owns the
    two-shape envelope parsing this function re-implements by hand.
  • It is a fourth call to the same endpoint on this surface (the switcher list, the
    writability courtesy gate and the namespace lookup are the other three, per
    objectui#7368).

Worth deciding

  1. Check res.ok (and the success: false envelope) and throw, so openManage's
    existing catch reports it on this file's shared studio-package-list sonner id and
    the sheet does not open. Cheapest, and reuses the posture that already exists here.
  2. Do not open the sheet on a null result regardless of how the null arose — a
    guard at the call site rather than at the fetch.
  3. Retire the hand-rolled fetch in favour of the packages-io reader plus a
    full-record variant, which would make 1 and the two adjacent observations one change.

Not obviously the same call as objectui#7368's (that one deliberately DEGRADES because
the top bar must survive a 503); here the affordance is a modal the author explicitly
asked for, so refusing to open it is a live option.

Re-check

grep -n "fetchFullPackage" -A 14 packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx

Related, not duplicates: objectui#7368 (the switcher's silence, merged), objectui#7821
(the false-deletion eviction, this file, in review), objectui#7373 (where a recovery
redirect should land).


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions