appwrite / appwrite/console

Self-hosted: 400 error on /v1/teams — unguarded billing.listOrganization() calls query non-existent 'platform' attribute

Open
#2,835 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Svelte
Stars
393
Forks
260
Avg merge
6h 53m
Merged PRs (30d)
24

Description

## Bug Description

On **self-hosted Appwrite 1.8.1** with **Console 7.5.7**, the organizations page (`/console/account/organizations`) returns a **400 Bad Request** error:

```
AppwriteException: Invalid `queries` param: Invalid query: Attribute not found in schema: platform
```

The console sends:
```
GET /v1/teams?queries[0]=offset(0)&queries[1]=limit(6)&queries[2]=orderDesc("")&queries[3]=equal("platform","appwrite")
→ 400 Bad Request
```

The `platform` attribute does not exist in the self-hosted teams collection schema.

## Root Cause

Two functions in `BrayF0lC.js` (billing utilities chunk) call `billing.listOrganization()` **without checking `isCloud`**:

1. **`XL()` — missingPaymentMethod check**
```js
// No isCloud guard!
async function XL() {
const e = await sdk.billing.listOrganization([
Query.notEqual("billingPlan", FREE),
Query.isNull("paymentMethodId"),
Query.isNull("backupPaymentMethodId"),
Query.equal("platform", Platform.Appwrite) // ← fails on self-hosted
]);
// ...shows missingPaymentMethod banner
}
```

2. **`JL()` — newDevUpgradePro check**
```js
// No isCloud guard!
async function JL(e) {
(await sdk.billing.listOrganization([
Query.notEqual("billingPlan", FREE) // ← also fails (billingPlan doesn't exist)
]))?.total
// ...
}
```

**Most other billing functions correctly guard with `isCloud`**, for example `HL()`:
```js
async function HL(e, t) {
if (!isCloud || !e) return; // ✅ Correct guard
// ...billing logic
}
```

The ternary patterns on other pages also correctly guard:
```js
isCloud
? await sdk.billing.listOrganization([Query.equal("platform", Platform.Appwrite)])
: await sdk.teams.list() // ✅ Correct fallback
```

## Environment

- **Appwrite Server**: 1.8.1 (Docker: `appwrite/appwrite:1.8.1`)
- **Appwrite Console**: 7.5.7 (Docker: `appwrite/console:7.5.7`)
- **PUBLIC_CONSOLE_MODE**: `self-hosted` (correctly set in env.js)
- **Browser**: Chrome 144 (macOS)

## Expected Behavior

On self-hosted installations, `XL()` and `JL()` should either:
- Check `isCloud` before calling `billing.listOrganization()`, or
- Be wrapped in a try/catch that silently handles the failure

## Workaround

Added `'platform'` to the `ALLOWED_ATTRIBUTES` array in `Teams.php` query validator, added `platform` column + index to the MariaDB `_console_teams` table, and added the attribute to the PHP collections config.

## Suggested Fix

Add `isCloud` guard to both functions, matching the pattern already used in `HL()`:

```js
async function XL() {
if (!isCloud) return; // ← Add this
// ...existing billing logic
}

async function JL(e) {
if (!isCloud) return; // ← Add this
// ...existing billing logic
}
```

## Reproduction Steps

1. Install self-hosted Appwrite 1.8.1 with Console 7.5.7
2. Set `PUBLIC_CONSOLE_MODE=self-hosted`
3. Log into the console
4. Navigate to Account → Organizations
5. Open browser DevTools → Network tab
6. See 400 error on `/v1/teams` with `equal("platform","appwrite")` query

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.