appwrite/appwrite · error · Appwrite\Extend\Exception

organization_id_missing

organization_id_missing

Error message

When using organization API key, make sure to pass x-appwrite-organization header with your organization ID.

What it means

Thrown in the organization-API-key validator (app/init/resources/request.php:1054) when a decoded API key carries a teamId but the x-appwrite-organization header is missing or does not match. Binds the key to its issuing organization.

Source

Thrown at app/init/resources/request.php:1054

        $userHeader = $request->getHeaderLine('x-appwrite-user');
        $organizationHeader = $request->getHeaderLine('x-appwrite-organization');
        $projectHeader = $request->getHeaderLine('x-appwrite-project');

        if (! empty($key->getProjectId())) {
            if (empty($projectHeader) || $projectHeader !== $key->getProjectId()) {
                throw new Exception(Exception::PROJECT_ID_MISSING);
            }
        }

        if (! empty($key->getUserId())) {
            if (empty($userHeader) || $userHeader !== $key->getUserId()) {
                throw new Exception(Exception::USER_ID_MISSING);
            }
        }

        if (! empty($key->getTeamId())) {
            if (empty($organizationHeader) || $organizationHeader !== $key->getTeamId()) {
                throw new Exception(Exception::ORGANIZATION_ID_MISSING);
            }
        }

        return $key;
    }, ['request', 'project', 'team', 'user']);

    $context->set('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) {
        $tokenJWT = $request->getParam('token');

        if (! empty($tokenJWT) && ! $project->isEmpty()) { // JWT authentication
            // Use a large but reasonable maxAge to avoid auto-exp when token has no expiry
            $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), RESOURCE_TOKEN_ALGORITHM, RESOURCE_TOKEN_MAX_AGE, RESOURCE_TOKEN_LEEWAY); // Instantiate with key, algo, maxAge and leeway.

            try {
                $payload = $jwt->decode($tokenJWT);
            } catch (JWTException $error) {
                return new Document([]);
            }

View on GitHub (pinned to cd368e707d)

Solutions

  1. Set x-appwrite-organization to the key's teamId.
  2. Confirm the teamId in the key matches the organization the client targets.
  3. Ensure proxies do not strip x-appwrite-organization.
  4. Configure the SDK to send both the key and the organization header together.

Example fix

// before
client.setHeader('x-appwrite-key', orgApiKey);
// after
client.setHeader('x-appwrite-key', orgApiKey);
client.setHeader('x-appwrite-organization', teamId);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure x-appwrite-organization is set whenever an org API key is used
function ensureOrgHeader(headers, keyTeamId) {
  if (keyTeamId && headers['x-appwrite-organization'] !== keyTeamId) {
    headers['x-appwrite-organization'] = keyTeamId;
  }
  return headers;
}

Prevention

When it happens

Trigger: Client authenticates with an organization API key whose payload includes a teamId, but x-appwrite-organization is absent or mismatched. The check at line ~1052 compares $organizationHeader !== $key->getTeamId().

Common situations: SDK not configured to send x-appwrite-organization when using an org API key; header stripped by proxy; key for team A used against a client pointing at team B; multi-org setup missing the header.

Related errors


AI-assisted analysis of appwrite/appwrite@cd368e707d (2026-08-12). Data as JSON: /api/errors/7be9db75e4979725. Report an issue: GitHub.