How to fix auth/invalid-last-sign-in-time: Last sign-in time must be valid UTC date in Firebase

FirebaseINTERMEDIATEMEDIUMUpdated Dec 22, 2025· 175 views

This Firebase Authentication error occurs when you attempt to update a user's last sign-in time with an invalid or malformed UTC date string. The error typically appears when using the Firebase Admin SDK to modify user records programmatically, especially during user migration, data synchronization, or custom authentication workflows.

Quick fix

Fixes auth/invalid-last-sign-in-time

// Correct - ISO 8601 UTC with "Z"
const correctTimestamp = "2025-01-15T10:30:00.000Z";

// Also acceptable (without milliseconds)
const correctTimestampSimple = "2025-01-15T10:30:00Z";
  1. Verify your timestamp format is valid UTC ISO 8601
  2. Convert existing timestamps to proper UTC format
  3. Update user with correct timestamp using Admin SDK
  4. Handle user migration scenarios
firebase — error
// Correct - ISO 8601 UTC with "Z"
const correctTimestamp = "2025-01-15T10:30:00.000Z";
// Also acceptable (without milliseconds)
const correctTimestampSimple = "2025-01-15T10:30:00Z";
auth/invalid-last-sign-in-time: Last sign-in time must be valid UTC date

What this error means

The "auth/invalid-last-sign-in-time" error in Firebase Authentication indicates that your application is trying to set or update a user's lastSignInTime field with a value that doesn't conform to Firebase's required UTC date format. Firebase stores authentication timestamps (like last sign-in time, creation time, and password update time) in a specific ISO 8601 UTC format. When you use the Admin SDK's updateUser() method or similar functions to modify user records, Firebase validates that any timestamp values you provide are properly formatted UTC dates. This error commonly occurs in scenarios like: 1. User migration: When migrating users from another authentication system to Firebase 2. Data synchronization: When syncing user data between Firebase and other systems 3. Custom authentication workflows: When implementing custom sign-in logic that updates user records 4. Backend user management: When administrative tools modify user properties The error prevents the operation from completing because Firebase cannot parse the provided timestamp string as a valid UTC date.

Typical symptoms

  • Firebase Admin SDK throws "auth/invalid-last-sign-in-time" error when calling updateUser()
  • User migration scripts fail with timestamp validation errors
  • Custom authentication workflows break when updating user records
  • Error appears in server logs with message "Last sign-in time must be valid UTC date"
  • User data synchronization between systems fails

Common causes

  1. Providing a non-UTC timestamp string (most common)
  2. Using local time format instead of UTC
  3. Incorrect ISO 8601 format (missing timezone indicator, wrong separators)
  4. Passing a JavaScript Date object instead of string
  5. Empty or null value for lastSignInTime field
  6. Timestamp string with invalid date components (e.g., February 30)
  7. Using milliseconds since epoch instead of ISO string
  8. Time zone offset format instead of "Z" for UTC

How to fix "auth/invalid-last-sign-in-time: Last sign-in time must be valid UTC date"

1Verify your timestamp format is valid UTC ISO 8601

Firebase requires UTC timestamps in ISO 8601 format ending with "Z". Check your current timestamp:

Correct format:

javascript
// Correct - ISO 8601 UTC with "Z"
const correctTimestamp = "2025-01-15T10:30:00.000Z";

// Also acceptable (without milliseconds)
const correctTimestampSimple = "2025-01-15T10:30:00Z";

Incorrect formats that cause the error:

javascript
// WRONG - Local time without timezone
const wrong1 = "2025-01-15T10:30:00";

// WRONG - With timezone offset instead of "Z"
const wrong2 = "2025-01-15T10:30:00+00:00";

// WRONG - JavaScript Date object (not string)
const wrong3 = new Date();

// WRONG - Milliseconds since epoch
const wrong4 = "1736929800000";

// WRONG - Custom format
const wrong5 = "January 15, 2025 10:30:00";

Quick validation function:

javascript
function isValidFirebaseTimestamp(timestamp) {
  if (typeof timestamp !== 'string') return false;
  // Must end with Z (UTC) and match ISO 8601 pattern
  const isoPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;
  return isoPattern.test(timestamp) && !isNaN(Date.parse(timestamp));
}
2Convert existing timestamps to proper UTC format

If you have timestamps in other formats, convert them to Firebase-compatible UTC:

From JavaScript Date object:

javascript
const date = new Date();
const firebaseTimestamp = date.toISOString(); // "2025-01-15T10:30:00.000Z"

From milliseconds since epoch:

javascript
const milliseconds = 1736929800000;
const date = new Date(milliseconds);
const firebaseTimestamp = date.toISOString();

From local time string (assuming it's in UTC):

javascript
const localTimeString = "2025-01-15T10:30:00";
const date = new Date(localTimeString + "Z"); // Add Z to treat as UTC
const firebaseTimestamp = date.toISOString();

From other timezone with offset:

javascript
const timezoneString = "2025-01-15T10:30:00-05:00"; // EST
const date = new Date(timezoneString);
const firebaseTimestamp = date.toISOString(); // Converts to UTC

Using a utility function:

javascript
function toFirebaseTimestamp(input) {
  if (input instanceof Date) {
    return input.toISOString();
  } else if (typeof input === 'string') {
    // Try to parse as date
    const date = new Date(input);
    if (isNaN(date.getTime())) {
      throw new Error('Invalid date string');
    }
    return date.toISOString();
  } else if (typeof input === 'number') {
    // Assume milliseconds
    return new Date(input).toISOString();
  } else {
    throw new Error('Unsupported input type');
  }
}
3Update user with correct timestamp using Admin SDK

Once you have a properly formatted timestamp, update the user correctly:

Using Firebase Admin SDK (Node.js):

javascript
const admin = require('firebase-admin');
const serviceAccount = require('./serviceAccountKey.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

async function updateUserLastSignIn(uid, timestamp) {
  try {
    // First, validate the timestamp
    if (!isValidFirebaseTimestamp(timestamp)) {
      throw new Error('Invalid timestamp format');
    }

    // Update the user
    await admin.auth().updateUser(uid, {
      lastSignInTime: timestamp,
    });

    console.log('User updated successfully');
  } catch (error) {
    console.error('Error updating user:', error.message);
    throw error;
  }
}

// Usage
const userId = 'user123';
const validTimestamp = new Date().toISOString(); // Current time in UTC

updateUserLastSignIn(userId, validTimestamp)
  .then(() => console.log('Done'))
  .catch(console.error);

Important considerations:
1. Permissions: Your service account needs firebaseauth.users.update permission
2. Rate limiting: Firebase has rate limits for user updates
3. Validation: Firebase validates other fields too (email, displayName, etc.)
4. Batch operations: For multiple users, consider batch processing with delays

4Handle user migration scenarios

When migrating users from another system, ensure proper timestamp conversion:

Migration script structure:

javascript
async function migrateUsers(legacyUsers) {
  const admin = require('firebase-admin');

  for (const legacyUser of legacyUsers) {
    try {
      // Convert legacy timestamp to Firebase format
      const firebaseTimestamp = convertLegacyTimestamp(legacyUser.lastLogin);

      // Create or update user in Firebase
      await admin.auth().updateUser(legacyUser.id, {
        email: legacyUser.email,
        displayName: legacyUser.name,
        lastSignInTime: firebaseTimestamp,
        // Other fields as needed
      });

      console.log('Migrated user: ' + legacyUser.email);

      // Add delay to avoid rate limiting
      await new Promise(resolve => setTimeout(resolve, 100));

    } catch (error) {
      console.error('Failed to migrate user ' + legacyUser.email + ':', error.message);
      // Log error but continue with other users
    }
  }
}

function convertLegacyTimestamp(legacyTimestamp) {
  // Handle various legacy formats
  if (legacyTimestamp instanceof Date) {
    return legacyTimestamp.toISOString();
  }

  if (typeof legacyTimestamp === 'string') {
    // Try common formats
    const formats = [
      'YYYY-MM-DD HH:mm:ss',
      'MM/DD/YYYY HH:mm:ss',
      'DD-MM-YYYY HH:mm:ss',
      // Add other formats your system uses
    ];

    for (const format of formats) {
      try {
        // Use a library like moment.js or date-fns for parsing
        const date = parseDate(legacyTimestamp, format);
        if (date) return date.toISOString();
      } catch (e) {
        // Try next format
      }
    }
  }

  // If conversion fails, use current time
  console.warn('Could not parse timestamp: ' + legacyTimestamp + ', using current time');
  return new Date().toISOString();
}

Migration best practices:
1. Test with a small batch first
2. Implement proper error handling and logging
3. Consider using Firebase's user import feature for large migrations
4. Validate all user data before migration
5. Have a rollback plan

5Test and validate your timestamp handling

Create comprehensive tests for your timestamp conversion and user update logic:

Unit tests for timestamp conversion:

javascript
const assert = require('assert');

describe('Timestamp conversion', () => {
  it('should convert Date object to Firebase format', () => {
    const date = new Date('2025-01-15T10:30:00Z');
    const result = toFirebaseTimestamp(date);
    assert.strictEqual(result, '2025-01-15T10:30:00.000Z');
  });

  it('should convert ISO string to Firebase format', () => {
    const result = toFirebaseTimestamp('2025-01-15T10:30:00Z');
    assert.strictEqual(result, '2025-01-15T10:30:00.000Z');
  });

  it('should reject invalid timestamp strings', () => {
    assert.throws(() => toFirebaseTimestamp('invalid-date'));
  });

  it('should handle milliseconds since epoch', () => {
    const ms = 1736929800000; // 2025-01-15T10:30:00Z
    const result = toFirebaseTimestamp(ms);
    assert.strictEqual(result, '2025-01-15T10:30:00.000Z');
  });
});

describe('Firebase timestamp validation', () => {
  it('should accept valid Firebase timestamps', () => {
    assert(isValidFirebaseTimestamp('2025-01-15T10:30:00.000Z'));
    assert(isValidFirebaseTimestamp('2025-01-15T10:30:00Z'));
  });

  it('should reject timestamps without Z', () => {
    assert(!isValidFirebaseTimestamp('2025-01-15T10:30:00'));
  });

  it('should reject timestamps with timezone offset', () => {
    assert(!isValidFirebaseTimestamp('2025-01-15T10:30:00+00:00'));
  });
});

Integration test for user update:

javascript
describe('User update integration', () => {
  let testUserId;

  before(async () => {
    // Create a test user
    const user = await admin.auth().createUser({
      email: 'test@example.com',
      password: 'test123',
    });
    testUserId = user.uid;
  });

  after(async () => {
    // Clean up test user
    await admin.auth().deleteUser(testUserId);
  });

  it('should update user with valid timestamp', async () => {
    const timestamp = new Date().toISOString();

    await admin.auth().updateUser(testUserId, {
      lastSignInTime: timestamp,
    });

    const updatedUser = await admin.auth().getUser(testUserId);
    assert.strictEqual(updatedUser.metadata.lastSignInTime, timestamp);
  });

  it('should reject invalid timestamp', async () => {
    const invalidTimestamp = 'invalid-date';

    try {
      await admin.auth().updateUser(testUserId, {
        lastSignInTime: invalidTimestamp,
      });
      assert.fail('Should have thrown error');
    } catch (error) {
      assert(error.code === 'auth/invalid-last-sign-in-time');
    }
  });
});
6Implement error handling and monitoring

Add robust error handling and monitoring for timestamp-related operations:

Error handling wrapper:

javascript
async function safeUpdateUser(uid, updates) {
  try {
    // Validate timestamp if present
    if (updates.lastSignInTime) {
      if (!isValidFirebaseTimestamp(updates.lastSignInTime)) {
        throw new Error('Invalid lastSignInTime format');
      }
    }

    const result = await admin.auth().updateUser(uid, updates);

    // Log successful update
    console.log({
      event: 'user_updated',
      userId: uid,
      timestamp: new Date().toISOString(),
      fields: Object.keys(updates),
    });

    return result;

  } catch (error) {
    // Log detailed error information
    console.error({
      event: 'user_update_failed',
      userId: uid,
      errorCode: error.code,
      errorMessage: error.message,
      timestamp: new Date().toISOString(),
      updates: updates,
      stack: error.stack,
    });

    // Re-throw for caller to handle
    throw error;
  }
}

Monitoring and alerts:
1. Log aggregation: Use services like Cloud Logging, Datadog, or Splunk
2. Error rate monitoring: Alert if error rate exceeds threshold
3. Latency monitoring: Track user update operation latency
4. Dashboard: Create dashboard showing:
- Successful/failed user updates
- Most common error types
- Peak usage times
- Migration progress (if applicable)

Alert configuration example:

yaml
# Example alert policy (Google Cloud Monitoring)
alert_policy:
  display_name: "High Firebase user update failure rate"
  condition:
    condition_threshold:
      filter: 'metric.type="logging.googleapis.com/user_defined" resource.type="global" metric.labels.event="user_update_failed"'
      aggregations:
        alignment_period: "300s"
        per_series_aligner: ALIGN_RATE
      comparison: COMPARISON_GT
      threshold_value: 0.05  # 5% failure rate
      duration: "600s"  # 10 minutes
  notification_channels:
    - "projects/project-id/notificationChannels/123456"

Advanced notes

### Understanding Firebase Authentication Timestamps

Firebase Authentication uses several timestamp fields for user metadata:

1. lastSignInTime: When the user last signed in successfully
2. creationTime: When the user account was created
3. passwordUpdateTime: When the password was last changed

All these fields use the same ISO 8601 UTC format requirement.

### Timezone Considerations

Why UTC is required:
- Consistency across servers in different timezones
- Avoids daylight saving time issues
- Simplifies comparison and sorting operations
- Aligns with Firebase's global infrastructure

Common timezone pitfalls:
1. Server timezone differences: Development vs production servers might have different timezone settings
2. Client-side time generation: Browser/device times may not be UTC
3. Database timezone settings: Existing databases might store times in local timezone

### Migration Strategies

For large-scale migrations:
1. Use Firebase Import Tool: For bulk user imports, use the official Firebase user import feature which handles timestamp conversion
2. Staged migration: Migrate users in batches with validation between batches
3. Dual-write approach: Write to both old and new systems during transition period
4. Validation phase: Run comparison checks between source and Firebase data

Timestamp reconstruction:
If source system doesn't have accurate timestamps:
1. Use account creation date if available
2. Use first activity date as proxy for last sign-in
3. Document assumptions in migration notes
4. Consider setting all migrated users with a known migration timestamp

### Performance Considerations

Rate limiting:
- Firebase Admin SDK has rate limits for user operations
- Typical limits: ~1,000 requests per second per project
- Implement exponential backoff for retries
- Use batch operations where possible

Optimization tips:
1. Cache user lookups: Reduce unnecessary getUser() calls
2. Batch updates: Group multiple field updates in single call
3. Async processing: Use queues for non-critical updates
4. Monitor quotas: Track usage against Firebase quotas

### Security Implications

Timestamp manipulation risks:
1. Account activity spoofing: Incorrect timestamps can hide suspicious activity
2. Audit trail integrity: Timestamps are crucial for security investigations
3. Compliance requirements: Some regulations require accurate audit trails

Best practices:
1. Validate all timestamps before writing to Firebase
2. Log timestamp changes for audit purposes
3. Implement approval workflows for manual user updates
4. Regularly audit user metadata for anomalies

### Testing Edge Cases

Test your implementation with:
1. Leap years: February 29 in leap years
2. Timezone transitions: Daylight saving time changes
3. Far future dates: Years beyond 2038 (32-bit Unix time limit)
4. Historical dates: Very old accounts (pre-1970)
5. Microsecond precision: Firebase supports millisecond precision

### Alternative Approaches

If timestamp conversion is too complex:
1. Omit timestamp: Let Firebase set default values
2. Use current time: For migrated users, use migration time as last sign-in
3. Custom metadata: Store original timestamps in Firestore or custom claims
4. External synchronization: Maintain timestamp mapping in external system

Frequently asked questions

What does "auth/invalid-last-sign-in-time" mean?
The "auth/invalid-last-sign-in-time" error in Firebase Authentication indicates that your application is trying to set or update a user's lastSignInTime field with a value that doesn't conform to Firebase's required UTC date format. Firebase stores authentication timestamps (like last sign-in time, creation time, and password update time) in a specific ISO 8601 UTC format. When you use the Admin SDK's updateUser() method or similar functions to modify user records, Firebase validates that any timestamp values you provide are properly formatted UTC dates.
How do I fix "auth/invalid-last-sign-in-time"?
This Firebase Authentication error occurs when you attempt to update a user's last sign-in time with an invalid or malformed UTC date string. The error typically appears when using the Firebase Admin SDK to modify user records programmatically, especially during user migration, data synchronization, or custom authentication workflows.
What causes "auth/invalid-last-sign-in-time"?
Providing a non-UTC timestamp string (most common) Using local time format instead of UTC Incorrect ISO 8601 format (missing timezone indicator, wrong separators)
Is the "auth/invalid-last-sign-in-time" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading