fix: prevent project Usage tab crash on missing usage breakdowns - #3142
Merged
Conversation
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.
Contributor
Greptile SummaryMakes the project Usage page resilient to omitted usage breakdowns and prevents failed attribution requests from producing unhandled promise rejections.
Confidence Score: 5/5The 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
Reviews (1): Last reviewed commit: "fix: prevent project Usage tab crash on ..." | Re-trigger Greptile |
ArnabChatterjee20k
approved these changes
Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
Column 52 on line 324 is the
.lengthread ondata.usage.executionsBreakdown. The error names'length', not'executionsBreakdown', sodata.usagewas present and populated — only that one field was missing from the response.@appwrite.io/consoletypes it as a requiredMetricBreakdown[], 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
executionsBreakdown,authPhoneCountryBreakdown) so a missing breakdown hides just its table instead of taking down the page.legendDatareduced overdatabasesReads/databasesWritesoutside any{#if}— this would have crashed even earlier had those been the missing fields.{#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 unhandledFailed to fetchrejection. 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.getUsageomitsexecutionsBreakdown. All four cloud regions report1.9.5, and the SDK is pinned to commit6be9e62, 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 errorsbun run lint— 0 errorsbun run test:unit— 239 passedbun run buildwas not run locally (the local Sentry release step 401s on an invalid dev token); CI covers it.