# How to Log Errors in Firebase Cloud Functions

- Tool: Firebase
- Difficulty: Beginner
- Time required: 10-15 min
- Compatibility: Firebase Cloud Functions v2, Node.js 18+, Blaze plan required
- Last updated: March 2026

## TL;DR

Firebase Cloud Functions v2 provides a built-in logger module with severity levels: logger.info(), logger.warn(), logger.error(), and logger.debug(). Import it from firebase-functions/logger and use structured logging with JSON objects for rich metadata. View logs in the Firebase Console under Functions > Logs or in Google Cloud Logging for advanced filtering and alerting.

## Error Logging in Firebase Cloud Functions

Effective error logging is critical for debugging Cloud Functions in production. This tutorial covers the Firebase Functions logger module, structured logging with JSON metadata, severity levels for categorizing log output, viewing logs in the Firebase Console and Google Cloud Logging, and setting up alerts to notify you when errors occur. You will learn patterns for logging errors in HTTP functions, Firestore triggers, and callable functions.

## Before you start

- A Firebase project on the Blaze plan
- Firebase CLI installed and logged in
- Cloud Functions initialized in your project (firebase init functions)
- At least one deployed Cloud Function

## Step-by-step guide

### 1. Import the Firebase Functions logger

The firebase-functions package includes a built-in logger module that integrates directly with Google Cloud Logging. Import it at the top of your functions file. The logger provides four severity levels: debug, info, warn, and error. Each level appears with a different severity in Cloud Logging, making it easy to filter for errors in production. Avoid using console.log() in production functions because it lacks severity levels and structured metadata.

```
import { logger } from 'firebase-functions/v2';
import { onRequest } from 'firebase-functions/v2/https';

// Use logger instead of console.log
export const myFunction = onRequest(async (req, res) => {
  logger.info('Function started', { method: req.method, path: req.path });

  try {
    // Your function logic here
    logger.info('Operation completed successfully');
    res.status(200).send('OK');
  } catch (error) {
    logger.error('Function failed', { error: String(error) });
    res.status(500).send('Internal error');
  }
});
```

**Expected result:** Your function logs appear with proper severity levels in Firebase Console and Cloud Logging.

### 2. Use structured logging with metadata objects

Pass a JSON object as the second argument to any logger method to attach structured metadata. This metadata appears as searchable fields in Cloud Logging, making it much easier to filter and investigate issues. Include relevant context like user IDs, document paths, request parameters, and error details. Structured logs are more useful than string interpolation because they support advanced queries.

```
import { logger } from 'firebase-functions/v2';
import { onDocumentCreated } from 'firebase-functions/v2/firestore';

export const onUserCreated = onDocumentCreated(
  'users/{userId}',
  async (event) => {
    const userId = event.params.userId;
    const userData = event.data?.data();

    logger.info('New user created', {
      userId,
      email: userData?.email,
      provider: userData?.provider,
      timestamp: new Date().toISOString()
    });

    try {
      // Send welcome email, create profile, etc.
      logger.info('Welcome email sent', { userId });
    } catch (error: any) {
      logger.error('Failed to process new user', {
        userId,
        errorCode: error.code,
        errorMessage: error.message,
        stack: error.stack
      });
    }
  }
);
```

**Expected result:** Log entries include structured JSON metadata that can be filtered and queried in Cloud Logging.

### 3. Log errors in callable functions with context

Callable functions (onCall) receive authentication context automatically. Include the caller's UID and other auth details in error logs to trace issues to specific users. Always log errors before throwing HttpsError so the error context is captured even though the client receives a generic error message.

```
import { logger } from 'firebase-functions/v2';
import { onCall, HttpsError } from 'firebase-functions/v2/https';

export const processOrder = onCall(async (request) => {
  const uid = request.auth?.uid;
  const orderData = request.data;

  logger.info('Processing order', {
    uid,
    orderId: orderData.orderId,
    amount: orderData.amount
  });

  if (!uid) {
    logger.warn('Unauthenticated order attempt', {
      ip: request.rawRequest.ip
    });
    throw new HttpsError('unauthenticated', 'Must be signed in');
  }

  try {
    // Process the order
    logger.info('Order processed successfully', {
      uid,
      orderId: orderData.orderId
    });
    return { success: true };
  } catch (error: any) {
    logger.error('Order processing failed', {
      uid,
      orderId: orderData.orderId,
      errorCode: error.code,
      errorMessage: error.message,
      stack: error.stack
    });
    throw new HttpsError('internal', 'Failed to process order');
  }
});
```

**Expected result:** Error logs include the user UID, order details, and full error information for debugging.

### 4. View logs in the Firebase Console

Open the Firebase Console, go to Functions in the left sidebar, and click the Logs tab. You can filter by function name, severity level, and time range. Each log entry shows the severity icon, timestamp, function name, and message. Click any entry to expand it and see the structured metadata. For more advanced filtering, click the 'View in Cloud Logging' link to open Google Cloud Logging with full query support.

**Expected result:** You can see your function's log output filtered by severity and function name in the Firebase Console.

### 5. Set up log-based alerts in Cloud Logging

Create alerts in Google Cloud Logging to notify you when errors occur in production. Go to Cloud Console > Logging > Logs Explorer, create a query that matches your error logs, then click Create Alert. Configure a notification channel (email, Slack, PagerDuty) and set the alert condition. This ensures you are notified immediately when functions fail instead of discovering errors hours or days later.

```
# Cloud Logging query to find all function errors
resource.type="cloud_function"
severity=ERROR
resource.labels.function_name="processOrder"

# Query to find specific error patterns
resource.type="cloud_function"
severity>=WARNING
jsonPayload.errorCode="PERMISSION_DENIED"
```

**Expected result:** You receive notifications when error-level logs are written by your Cloud Functions.

## Complete code example

File: `functions/src/index.ts`

```typescript
import { logger } from 'firebase-functions/v2';
import { onRequest, onCall, HttpsError } from 'firebase-functions/v2/https';
import { onDocumentCreated } from 'firebase-functions/v2/firestore';
import { initializeApp } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';

initializeApp();
const db = getFirestore();

// HTTP function with structured error logging
export const api = onRequest(async (req, res) => {
  const requestId = crypto.randomUUID();
  logger.info('API request received', {
    requestId,
    method: req.method,
    path: req.path,
    userAgent: req.headers['user-agent']
  });

  try {
    const result = await db.collection('items').get();
    logger.info('Query successful', {
      requestId,
      documentCount: result.size
    });
    res.json({ items: result.docs.map(d => d.data()) });
  } catch (error: any) {
    logger.error('API request failed', {
      requestId,
      errorCode: error.code,
      errorMessage: error.message,
      stack: error.stack
    });
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Callable function with auth context logging
export const updateProfile = onCall(async (request) => {
  const uid = request.auth?.uid;
  if (!uid) {
    logger.warn('Unauthenticated profile update attempt');
    throw new HttpsError('unauthenticated', 'Sign in required');
  }

  try {
    await db.collection('users').doc(uid).update(request.data);
    logger.info('Profile updated', { uid });
    return { success: true };
  } catch (error: any) {
    logger.error('Profile update failed', {
      uid,
      errorMessage: error.message
    });
    throw new HttpsError('internal', 'Update failed');
  }
});

// Firestore trigger with error logging
export const onOrderCreated = onDocumentCreated(
  'orders/{orderId}',
  async (event) => {
    const orderId = event.params.orderId;
    const order = event.data?.data();

    logger.info('New order received', {
      orderId,
      userId: order?.userId,
      total: order?.total
    });

    try {
      // Process order logic
      logger.info('Order processed', { orderId });
    } catch (error: any) {
      logger.error('Order processing failed', {
        orderId,
        errorCode: error.code,
        errorMessage: error.message,
        stack: error.stack
      });
    }
  }
);
```

## Common mistakes

- **Using console.log() instead of the Firebase logger in production functions** — undefined Fix: Replace console.log() with logger.info() and console.error() with logger.error(). The Firebase logger adds proper severity levels and structured metadata support that console methods lack.
- **Logging sensitive data like API keys, passwords, or full user tokens** — undefined Fix: Never log sensitive information. Redact or mask sensitive fields before including them in log metadata. Log user IDs and request IDs instead of full tokens.
- **Not including enough context in error logs to reproduce the issue** — undefined Fix: Always include the function name, relevant document IDs, user UID, and the full error object (code, message, stack) in error log metadata.
- **Forgetting to log before throwing HttpsError in callable functions** — undefined Fix: HttpsError sends a sanitized message to the client but does not automatically create a log entry. Always call logger.error() before throwing the error so the details are captured in Cloud Logging.

## Best practices

- Use the firebase-functions/v2 logger module instead of console.log for proper severity and metadata
- Attach structured JSON metadata to every log entry for searchable, filterable logs
- Include request IDs or correlation IDs to trace a single operation across multiple log entries
- Log at the appropriate severity level: debug for development, info for normal operations, warn for recoverable issues, error for failures
- Never log sensitive data including passwords, API keys, tokens, or personally identifiable information
- Set up log-based alerts in Cloud Logging for ERROR severity to catch production issues immediately
- Log both the start and completion of important operations to measure duration and identify hangs
- Include the error stack trace in error logs to pinpoint the exact line where failures occur

## Frequently asked questions

### What is the difference between console.log and the Firebase logger?

The Firebase logger (imported from firebase-functions/v2) writes structured logs with severity levels (INFO, WARNING, ERROR) that integrate with Google Cloud Logging. console.log writes plain text logs without severity, making them harder to filter and alert on in production.

### How long are Cloud Functions logs retained?

By default, Cloud Logging retains logs for 30 days. You can configure longer retention periods or export logs to BigQuery or Cloud Storage for permanent archival. Custom retention is available at additional cost.

### Can I view logs for a specific function only?

Yes. In the Firebase Console, go to Functions > Logs and use the function name dropdown to filter. In Cloud Logging, add resource.labels.function_name="yourFunctionName" to your query.

### Does logger.debug() output appear in production?

By default, DEBUG level logs are not visible in production. Set the minimum log level to DEBUG in your function configuration to enable them. Keep debug logging disabled in production to reduce noise and logging costs.

### How do I set up email alerts for function errors?

Go to Google Cloud Console > Logging > Logs Explorer, write a query for severity=ERROR with your function name, click Create Alert, and configure an email notification channel. You can also use Slack, PagerDuty, or webhook notification channels.

### Are there costs associated with Cloud Functions logging?

Google Cloud Logging provides 50 GB of logs ingestion free per month. Beyond that, logging costs $0.50/GB. High-volume functions with verbose logging can generate significant log volume, so use appropriate severity levels and avoid logging large payloads.

### Can RapidDev help set up monitoring and alerting for Firebase Functions?

Yes. RapidDev can implement comprehensive logging, monitoring dashboards in Cloud Monitoring, and alerting pipelines for your Firebase Cloud Functions, ensuring you catch production issues before they impact users.

---

Source: https://www.rapidevelopers.com/firebase-tutorial/how-to-log-errors-in-firebase-functions
© RapidDev — https://www.rapidevelopers.com/firebase-tutorial/how-to-log-errors-in-firebase-functions
