appwrite/appwrite · error · Appwrite\Extend\Exception
user_jwt_and_cookie_set
user_jwt_and_cookie_set
Error message
JWT and cookie used in the same request. Use either `setJWT` or `setCookie`. Learn about which authentication method to use in the SSR docs: https://appwrite.io/docs/products/auth/server-side-rendering
What it means
The HTTP-request counterpart of error 301. Thrown in app/init/resources/request.php:526 when an inbound HTTP request resolves a non-empty user from the session cookie/store AND also carries an x-appwrite-jwt header. Appwrite disallows mixing session and JWT credentials in one HTTP request; the SSR docs are referenced for choosing one method.
Source
Thrown at app/init/resources/request.php:526
/** @var User $user */
$user = $dbForProject->getDocument('users', $store->getProperty('id', ''));
}
}
}
}
if (
! $user ||
$user->isEmpty() // Check a document has been found in the DB
|| ! $user->sessionVerify($store->getProperty('secret', ''), $proofForToken)
) { // Validate user has valid login token
$user = new User([]);
}
$authJWT = $request->getHeaderLine('x-appwrite-jwt', '');
if (! empty($authJWT) && ! $project->isEmpty()) { // JWT authentication
if (! $user->isEmpty()) {
throw new Exception(Exception::USER_JWT_AND_COOKIE_SET);
}
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0);
try {
$payload = $jwt->decode($authJWT);
} catch (JWTException $error) {
throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage());
}
$jwtUserId = $payload['userId'] ?? '';
if (! empty($jwtUserId)) {
if ($mode === APP_MODE_ADMIN) {
/** @var User $user */
$user = $dbForPlatform->getDocument('users', $jwtUserId);
} else {
/** @var User $user */
$user = $dbForProject->getDocument('users', $jwtUserId);
}View on GitHub (pinned to cd368e707d)
Solutions
- For each HTTP call use EITHER setSession (cookie) OR setJWT, never both.
- Clear the session cookie before making JWT-authenticated server-side calls.
- In SSR, segregate client-side (cookie) and server-side (JWT) SDK instances so headers never combine.
- Inspect outbound request headers to confirm a single credential type.
Example fix
// before — SSR fetch sends both client.setSession(sessionCookie); client.setJWT(jwt); // after — server-side call uses JWT only client.setJWT(jwt);
Defensive patterns
Strategy: validation
Validate before calling
// Before each SSR HTTP call, ensure session and JWT are mutually exclusive
function assertSingleAuth(sessionCookie: string | null, jwt: string | null) {
if (sessionCookie && jwt) {
throw new Error('Do not send session and JWT together; choose one.');
}
} Try / catch
// Recover by dropping the cookie and retrying with JWT
try {
await databases.listDocuments();
} catch (e) {
if (e.code === 'user_jwt_and_cookie_set') {
client.headers['Cookie'] = '';
await databases.listDocuments();
} else throw e;
} Prevention
- Maintain separate SDK instances for SSR (JWT) and browser (cookie).
- Clear session cookies on logout before issuing JWT calls.
- Inspect request headers in dev to confirm a single auth method.
When it happens
Trigger: An HTTP API call (any /v1 endpoint) that has a valid session resolving to a user (via sessionVerify on the store secret/proof token) AND also sets x-appwrite-jwt. The !$user->isEmpty() guard trips before JWT decode.
Common situations: SSR framework holding a session cookie while the server-side fetch also attaches a JWT; SDK configured with both setSession and setJWT; cookie not cleared on logout before issuing a JWT-authenticated call; reverse proxy injecting cookies.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- user_jwt_and_cookie_set
- user_api_key_and_session_set
- user_api_key_and_session_set
- user_jwt_invalid
- user_not_found
AI-assisted analysis of appwrite/appwrite@cd368e707d (2026-08-12).
Data as JSON: /api/errors/c9167405d3ba5b42.
Report an issue: GitHub.