Skip to content

Pages Functions Error Handling & Debugging

DodaTech Updated 2026-06-23 4 min read

In this tutorial, you'll learn about Pages Functions Error Handling & Debugging. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

This tutorial explains error handling and debugging techniques for Cloudflare Pages Functions, including try-catch patterns, error responses, logging strategies, and common runtime issues. Serverless applications require robust error handling because failed requests return errors to users without server-side retry logic. The DodaTech API Gateway catches every error and returns structured JSON responses so clients always receive a valid response.

Error Handling Patterns

Wrap your function logic in try-catch blocks to handle both synchronous and asynchronous failures gracefully.

flowchart LR
  A[Incoming request] --> B[Try block]
  B --> C{Success?}
  C -->|Yes| D[Return response]
  C -->|No| E[Catch block]
  E --> F[Log error]
  F --> G[Return error response]
  style D fill:#f90,color:#fff
  style G fill:#f90,color:#fff

Structured Error Responses

Always return a consistent error format so clients can handle failures predictably.

// functions/utils/errors.js
export class AppError extends Error {
  constructor(statusCode, message, details) {
    super(message);
    this.statusCode = statusCode;
    this.details = details || null;
  }

  toResponse() {
    const body = {
      error: true,
      message: this.message,
      statusCode: this.statusCode
    };

    if (this.details) {
      body.details = this.details;
    }

    return new Response(JSON.stringify(body), {
      status: this.statusCode,
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

// Usage
export async function onRequest(context) {
  try {
    const userId = context.params.id;

    if (!userId || isNaN(userId)) {
      throw new AppError(400, 'Invalid user ID', { expected: 'number', received: userId });
    }

    const user = await context.env.DB.prepare(
      'SELECT * FROM users WHERE id = ?'
    ).bind(parseInt(userId)).first();

    if (!user) {
      throw new AppError(404, 'User not found');
    }

    return new Response(JSON.stringify(user), {
      headers: { 'Content-Type': 'application/json' }
    });
  } catch (error) {
    console.error('Handler failed:', error.message);
    if (error instanceof AppError) {
      return error.toResponse();
    }
    return new AppError(500, 'Internal server error').toResponse();
  }
}
// GET /api/users/abc -> 400: {"error":true,"message":"Invalid user ID","statusCode":400,"details":{"expected":"number","received":"abc"}}
// GET /api/users/999 -> 404: {"error":true,"message":"User not found","statusCode":404}

Debugging with Logs

Use console.log and console.error to debug function behavior. Logs appear in the Cloudflare dashboard under your Pages project Functions tab.

// functions/api/debug.js
export async function onRequest(context) {
  const requestInfo = {
    method: context.request.method,
    url: context.request.url,
    headers: Object.fromEntries(context.request.headers),
    params: context.params,
    time: new Date().toISOString()
  };

  console.log('Request info:', JSON.stringify(requestInfo, null, 2));

  try {
    const body = await context.request.text();
    console.log('Request body:', body);

    const response = new Response('OK', {
      headers: { 'Content-Type': 'text/plain' }
    });

    console.log('Response:', response.status);
    return response;
  } catch (error) {
    console.error('Body parse error:', error.message);
    return new Response('Error reading body', { status: 400 });
  }
}
// Log output:
// Request info: { "method": "POST", "url": "https://example.com/api/debug", "time": "2026-06-23T12:00:00.000Z" }
// Request body: {"test":true}
// Response: 200

Common Runtime Errors

Understanding frequent runtime errors helps you debug faster.

// Simulate and handle common Pages Function errors
async function simulateErrors() {
  const errors = {
    'UNDEFINED_BINDING': function() {
      try {
        return context.env.MISSING_BINDING.get('key');
      } catch (e) {
        return { type: 'ReferenceError', message: 'Binding MISSING_BINDING is not configured in dashboard' };
      }
    },
    'TIMEOUT': function() {
      return { type: 'TimeoutError', message: 'Function exceeded CPU time limit of 30 seconds' };
    },
    'SYNTAX': function() {
      try {
        JSON.parse('invalid json');
      } catch (e) {
        return { type: 'SyntaxError', message: 'Invalid JSON: Unexpected token in JSON at position 8' };
      }
    }
  };

  console.log('UNDEFINED_BINDING:', errors.UNDEFINED_BINDING());
  console.log('TIMEOUT:', errors.TIMEOUT());
  console.log('SYNTAX:', errors.SYNTAX());
}
simulateErrors();
// Expected output:
// UNDEFINED_BINDING: { type: 'ReferenceError', message: 'Binding MISSING_BINDING is not configured in dashboard' }
// TIMEOUT: { type: 'TimeoutError', message: 'Function exceeded CPU time limit of 30 seconds' }
// SYNTAX: { type: 'SyntaxError', message: 'Invalid JSON: Unexpected token in JSON at position 8' }

FAQ

How do I view Pages Function logs in the dashboard?

Navigate to your Pages project, click the Functions tab, then select Logs. You will see console output from your function executions. Logs are retained for 72 hours on the free plan.

What is the maximum response size for a Pages Function?

The maximum response body size is 25 MB for free plans and 100 MB for paid plans. Larger responses should use streaming or be served from R2 object storage instead.

Can I set up error notifications for Pages Functions?

Not directly. Use the Cloudflare API to poll for function errors or configure Logpush to send logs to an external service that supports alerting, such as Datadog or Sentry.

Practice Questions

  1. What HTTP status code should a validation error return?
  2. Which property on the AppError class determines the HTTP response status?
  3. How can you determine if a binding name is misconfigured from a log message?

Summary

Robust error handling in Pages Functions uses try-catch blocks, structured error responses, and consistent logging. Debug with console output visible in the Cloudflare dashboard. Common errors include missing bindings, timeouts, and syntax issues. Always return valid JSON error responses so clients can handle failures gracefully.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — security-first tools for the modern web.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro