Skip to content

fix: prevent project Usage tab crash on missing usage breakdowns - #3142

Merged
HarshMN2345 merged 1 commit into
mainfrom
fix-usage-tab-breakdown-crash
Jul 27, 2026
Merged

fix: prevent project Usage tab crash on missing usage breakdowns#3142
HarshMN2345 merged 1 commit into
mainfrom
fix-usage-tab-breakdown-crash

Conversation

@HarshMN2345

Copy link
Copy Markdown
Member

What

The project Settings → Usage tab did not render at all, while every other Settings tab worked. Reproduced on a Pro project and while impersonating a reporting user.

Root cause

Frontend, not the API. The load function succeeded — the crash was in the page component's render:

Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at +page.svelte:324:52

Column 52 on line 324 is the .length read on data.usage.executionsBreakdown. The error names 'length', not 'executionsBreakdown', so data.usage was present and populated — only that one field was missing from the response. @appwrite.io/console types it as a required MetricBreakdown[], so the code trusted it unconditionally.

Because a throw during render aborts the whole render pass, nothing mounted. That's why the tab highlight moved to Usage while the previously active tab's content stayed on screen, rather than an error page appearing. Other Settings tabs are unaffected because none of them touch this field.

Changes

  • Optional-chain both breakdown-table guards (executionsBreakdown, authPhoneCountryBreakdown) so a missing breakdown hides just its table instead of taking down the page.
  • Guard two latent instances of the same class on this page, since the response demonstrably omits array fields the SDK types as required:
    • legendData reduced over databasesReads/databasesWrites outside any {#if} — this would have crashed even earlier had those been the missing fields.
    • The db chart's {#if dbReads || dbWrites} passes when only one array exists, but the body mapped both.
  • +layout.svelte: the attribution ping was fire-and-forget with no .catch(), so a blocked request surfaced as an unhandled Failed to fetch rejection. Unrelated to the Usage tab and never affected rendering, but it was obscuring real errors in the console while debugging this.

These are null-guards rather than defaulting the arrays to [], because [] is truthy and would flip several {#if} empty-state checks — silently replacing "No data to show" cards with empty charts.

Follow-up needed (not in this PR)

This makes the console resilient, but does not explain why project.getUsage omits executionsBreakdown. All four cloud regions report 1.9.5, and the SDK is pinned to commit 6be9e62, which declares the field as required. So either the pinned SDK is ahead of deployed cloud, or the API conditionally drops breakdown fields.

Until that's resolved the per-function executions breakdown table won't appear for affected projects. Left out of scope here since it spans the cloud/edge repos — worth checking whether the pin needs to move or the API needs fixing.

Testing

  • bun run check — 0 errors
  • bun run lint — 0 errors
  • bun run test:unit — 239 passed
  • Verified by the reporter against a local dev server on the affected project; the Usage tab now renders.

bun run build was not run locally (the local Sentry release step 401s on an invalid dev token); CI covers it.

The project Settings > Usage tab failed to render entirely, while every
other Settings tab worked. The API request succeeded; the crash was in
the page component's render:

    Uncaught TypeError: Cannot read properties of undefined (reading 'length')
        at +page.svelte:324

`data.usage.executionsBreakdown` was undefined. The console SDK types it
as a required `MetricBreakdown[]`, so the guard read `.length` on it
unconditionally. Because a throw during render aborts the whole render
pass, nothing mounted -- which is why the tab highlight moved to Usage
while the previously active tab's content stayed on screen instead of an
error page being shown.

Optional-chain both breakdown-table guards (`executionsBreakdown` and
`authPhoneCountryBreakdown`) so a missing breakdown hides just its table.

Also guard two latent instances of the same class on this page, since the
response demonstrably omits array fields the SDK types as required:

- `legendData` reduced over `databasesReads`/`databasesWrites` outside any
  `{#if}`, so it would have crashed even earlier had those been missing.
- The db chart's `{#if dbReads || dbWrites}` passes when only one array is
  present, but the body mapped both.

These are null-guards rather than defaulting the arrays to `[]`, because
`[]` is truthy and would flip several `{#if}` empty-state checks, silently
replacing "No data to show" cards with empty charts.

Separately, the attribution ping in `+layout.svelte` was fire-and-forget
with no `.catch()`, so a blocked request surfaced as an unhandled
`Failed to fetch` rejection that obscured real errors in the console.
@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Makes the project Usage page resilient to omitted usage breakdowns and prevents failed attribution requests from producing unhandled promise rejections.

  • Safely derives database chart series and legend totals when read or write metrics are absent.
  • Hides execution and phone-country breakdown tables when their arrays are absent.
  • Handles rejected source-attribution requests as best-effort tracking.

Confidence Score: 5/5

The PR appears safe to merge, with the changed paths handling absent usage data and rejected attribution requests without introducing a concrete failure.

The usage fallbacks provide valid empty arrays to chart computations while preserving the existing no-data state when both series are absent, and the asynchronous attribution call now handles its rejected promise.

Important Files Changed

Filename Overview
src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.svelte Adds null-safe handling for optional database metrics and usage breakdown arrays without changing the existing empty-state guard.
src/routes/+layout.svelte Catches failures from the optional fire-and-forget source-attribution request, preventing unhandled rejections.

Reviews (1): Last reviewed commit: "fix: prevent project Usage tab crash on ..." | Re-trigger Greptile

@HarshMN2345
HarshMN2345 merged commit 5c5c83e into main Jul 27, 2026
4 checks passed
@HarshMN2345
HarshMN2345 deleted the fix-usage-tab-breakdown-crash branch July 27, 2026 14:00
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.

2 participants