Skip to content

fix(billing): avoid crash when billingPlanDetails is undefined in ContainerButton#2999

Open
singhvishalkr wants to merge 1 commit intoappwrite:mainfrom
singhvishalkr:fix-containerbutton-billing-optional
Open

fix(billing): avoid crash when billingPlanDetails is undefined in ContainerButton#2999
singhvishalkr wants to merge 1 commit intoappwrite:mainfrom
singhvishalkr:fix-containerbutton-billing-optional

Conversation

@singhvishalkr
Copy link
Copy Markdown

Fixes #2975.

Symptom

On Appwrite 1.9.0 self-hosted, opening Project > Functions > Templates blanks the page with:

Uncaught TypeError: can't access property "group", n().billingPlanDetails is undefined

The same stack trace was previously reported against Auth Security and fixed by #2958; the underlying source still lives in src/lib/layout/containerButton.svelte, which is also used by the Functions Templates page and several other surfaces, so the bug resurfaces there.

Root cause

ContainerButton computes its default tooltipContent at component instantiation:

export let tooltipContent =
    $organization?.billingPlanDetails.group === BillingPlanGroup.Starter
        ? `Upgrade to add more ${title.toLocaleLowerCase()}`
        : `You've reached the ${title.toLocaleLowerCase()} limit for the ${
              $organization?.billingPlanDetails.name
          } plan`;

On self-hosted deployments, organization is populated but billingPlanDetails is undefined (there's no billing system). The optional chain stops at organization, but .billingPlanDetails.group / .billingPlanDetails.name are direct property reads, so the expression throws the moment any page containing a ContainerButton mounts.

Fix

Promote both property reads to optional chaining:

-    $organization?.billingPlanDetails.group === BillingPlanGroup.Starter
+    $organization?.billingPlanDetails?.group === BillingPlanGroup.Starter
...
-                  $organization?.billingPlanDetails.name
+                  $organization?.billingPlanDetails?.name

On cloud, behaviour is unchanged -- billingPlanDetails is always populated, both reads resolve normally. On self-hosted, group becomes undefined (falling through to the plan-limit branch with undefined in place of the plan name), but the tooltip is only shown when the wrapping disabled prop is true, which self-hosted never hits via this path, so the cosmetic fallback is acceptable and the crash is gone.

…ng in ContainerButton

Self-hosted deployments populate organization but leave billingPlanDetails undefined (there is no billing plan). ContainerButton precomputes the default tooltipContent at component instantiation with organization?.billingPlanDetails.group and billingPlanDetails.name, so the moment any page that renders a ContainerButton (e.g. Project > Functions > Templates) loads on self-hosted, Svelte throws a TypeError and the rest of the view blanks out.

This was already observed on the Auth Security page and addressed there in appwrite#2958; the same pattern is still live in containerButton.svelte for every other consumer.

Switch both property reads to optional chaining so the tooltip falls back gracefully on self-hosted.

Fixes appwrite#2975.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

Adds optional chaining to two billingPlanDetails property reads in ContainerButton, fixing an Uncaught TypeError that blanked pages (Functions Templates, Auth Security, etc.) on self-hosted deployments where billingPlanDetails is undefined. On cloud the behavior is unchanged; on self-hosted the tooltip falls back to showing undefined for the plan name, but the tooltip is only rendered when disabled is true, which self-hosted deployments never reach through this path.

Confidence Score: 5/5

Safe to merge — minimal, targeted fix with no behavior change on cloud and correct crash prevention on self-hosted.

Only two characters changed (two ?. additions), directly addressing a well-understood crash with no side effects on the primary cloud path. No P0/P1 findings remain.

No files require special attention.

Important Files Changed

Filename Overview
src/lib/layout/containerButton.svelte Adds optional chaining on billingPlanDetails?.group and billingPlanDetails?.name to prevent a crash when billingPlanDetails is undefined on self-hosted deployments.

Reviews (1): Last reviewed commit: "fix(billing): don't access billingPlanDe..." | Re-trigger Greptile

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.

Functions Templates not working in 1.9.0 self-hosted

1 participant