The auth/invalid-page-token error occurs when paginating through Firebase users with an expired or invalid pageToken. Fix it by using tokens immediately after receiving them and always restarting pagination from the beginning if a token expires.
Firebase Admin SDK throws this error when you attempt to retrieve the next page of users using a pageToken that is no longer valid. Page tokens in Firebase are short-lived credentials designed for immediate use in consecutive pagination requests. If you store a token and attempt to use it later, or if the token is corrupted during transmission, Firebase rejects it with this error. This is a pagination-specific issue that occurs only when using the listUsers() method with a pageToken parameter.
Page tokens are designed to be used immediately in the next request. Never store tokens for later use. Implement pagination in a synchronous loop:
Node.js/JavaScript:
const listAllUsers = async (nextPageToken) => {
try {
const listUsersResult = await admin.auth().listUsers(1000, nextPageToken);
// Process the current batch of users
listUsersResult.users.forEach((userRecord) => {
console.log('user', userRecord.uid, userRecord.email);
});
// Immediately use the next token if it exists
if (listUsersResult.pageToken) {
return await listAllUsers(listUsersResult.pageToken);
}
} catch (error) {
console.error('Error listing users:', error);
throw error;
}
};
// Start pagination from the beginning
await listAllUsers();
TypeScript:
async function listAllUsers(nextPageToken?: string): Promise<void> {
const listUsersResult = await admin.auth().listUsers(1000, nextPageToken);
listUsersResult.users.forEach((userRecord) => {
processUser(userRecord);
});
if (listUsersResult.pageToken) {
await listAllUsers(listUsersResult.pageToken);
}
}
await listAllUsers();
If you get an auth/invalid-page-token error, handle it by restarting pagination without a token:
async function safeListAllUsers(nextPageToken?: string): Promise<void> {
try {
const listUsersResult = await admin.auth().listUsers(1000, nextPageToken);
for (const userRecord of listUsersResult.users) {
// Process each user
await processUserData(userRecord);
}
if (listUsersResult.pageToken) {
await safeListAllUsers(listUsersResult.pageToken);
}
} catch (error: any) {
if (error.code === 'auth/invalid-page-token') {
console.warn('Page token expired, restarting from beginning');
// Start fresh without token
await safeListAllUsers();
} else {
throw error;
}
}
}
await safeListAllUsers();
Do not attempt to persist page tokens. They are ephemeral and will expire. If you need to resume user listing:
WRONG - storing tokens in database:
const result = await admin.auth().listUsers(1000, lastToken);
// DON'T DO THIS:
await db.pagination.save({
pageToken: result.pageToken,
lastProcessedAt: new Date()
});
CORRECT - process all users in one session:
const listAllUsers = async (nextPageToken?: string) => {
const result = await admin.auth().listUsers(1000, nextPageToken);
for (const user of result.users) {
// Process user immediately
await handleUser(user);
}
if (result.pageToken) {
// Token is only valid right now, use it immediately
return await listAllUsers(result.pageToken);
}
};
If you need to resume user processing between application restarts, use a different strategy:
- Track processed user IDs, not page tokens
- Start fresh pagination and skip already-processed users
- Use database checkpoints with user IDs, not tokens
Page tokens are project-specific. Verify you're using the same Firebase project:
Check your Firebase Admin SDK initialization:
const admin = require('firebase-admin');
const serviceAccount = require('./path-to-service-account-key.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://YOUR-PROJECT.firebaseio.com"
});
Update to the latest Firebase Admin SDK:
npm update firebase-admin
Verify the service account has proper permissions in Firebase Console:
- Go to Project Settings
- Service Accounts tab
- Regenerate private key if needed
- Ensure the key file is current
Do not use page tokens from a different Firebase project or with a different authentication credential.
For background jobs that list users, structure your code to handle token expiration:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
export const syncAllUsers = functions.pubsub
.schedule('every 24 hours')
.onRun(async (context) => {
try {
await processAllUsers();
console.log('Successfully synced all users');
} catch (error) {
console.error('Error syncing users:', error);
// Don't throw - let Cloud Functions retry automatically
}
});
async function processAllUsers(nextPageToken?: string): Promise<void> {
try {
const result = await admin.auth().listUsers(1000, nextPageToken);
// Process users in batch
await Promise.all(
result.users.map(user => saveUserToDatabase(user))
);
console.log(Processed ${result.users.length} users);
if (result.pageToken) {
// Recursively process next page with immediate token use
await processAllUsers(result.pageToken);
}
} catch (error: any) {
if (error.code === 'auth/invalid-page-token') {
// Log and restart
console.warn('Page token expired, starting fresh pagination');
await processAllUsers();
} else {
throw error;
}
}
}
async function saveUserToDatabase(user: admin.auth.UserRecord): Promise<void> {
// Save user data to your database
await admin.firestore().collection('users').doc(user.uid).set({
email: user.email,
displayName: user.displayName,
createdAt: user.metadata.creationTime
});
}
The auth/invalid-page-token error is primarily a design constraint of the Firebase Admin SDK. Page tokens use ephemeral session-like credentials that expire after a short period (typically minutes). For large-scale user operations, consider batch processing within a single operation window. If you need to process millions of users, structure your code to handle token expiration gracefully by restarting pagination. Alternatively, use Firebase Security Rules and Firestore to index users in a way that allows querying without pagination. Some deployments use message queues (Cloud Tasks, Pub/Sub) to maintain long-running pagination contexts, but tokens still cannot be shared across multiple invocations. Always test pagination with large user bases (10,000+ users) in your staging environment to catch token-related issues before production.
messaging/UNSPECIFIED_ERROR: No additional information available
How to fix "messaging/UNSPECIFIED_ERROR: No additional information available" in Firebase Cloud Messaging
App Check: reCAPTCHA Score Too Low
App Check reCAPTCHA Score Too Low
storage/invalid-url: Invalid URL format for Cloud Storage reference
How to fix invalid URL format in Firebase Cloud Storage
auth/missing-uid: User ID identifier required
How to fix "auth/missing-uid: User ID identifier required" in Firebase
auth/invalid-argument: Invalid parameter passed to method
How to fix "auth/invalid-argument: Invalid parameter passed to method" in Firebase