How to Troubleshoot Open-SEO Errors: A Complete Developer Guide

Open-SEO normalizes every server-side exception into a typed error code through a layered middleware pipeline, enabling you to distinguish between validation issues, configuration mistakes, and upstream failures by checking the code property returned to the client.

Open-SEO runs as a Cloudflare Worker (or Docker container in self-hosted mode) and implements a strict error-handling architecture that converts raw exceptions into predictable, client-safe responses. Understanding this pipeline allows you to quickly pinpoint whether an error stems from user input, missing environment variables, or external API failures. This guide walks you through the complete error flow, common failure categories, and the exact source files you need to examine when troubleshooting.

Understanding the Open-SEO Error Handling Pipeline

The error resolution process follows a strict sequence from request entry to client response. Each layer adds context while stripping sensitive internal details.

Request Entry and Middleware Wrapping

All HTTP requests enter through src/server.ts at the fetch function, which routes traffic to API endpoints, MCP handlers, or chat agents. Immediately after routing, the errorHandlingMiddleware (defined in src/middleware/errorHandling.ts) wraps every server function execution. This middleware serves as the central catch-all that intercepts any thrown value, distinguishes validator errors from business-logic failures, logs the stack trace, and forwards a sanitized error to the client.

AppError Normalization and Code Classification

When the middleware catches an exception, it normalizes the error into an AppError object defined in src/server/lib/errors.ts. These objects carry a typed code property drawn from the canonical list in src/shared/error-codes.ts. Available codes include VALIDATION_ERROR, AUTH_CONFIG_MISSING, RATE_LIMITED, UPSTREAM_UNAVAILABLE, and INTERNAL_ERROR. The AppError constructor ensures every error has a machine-readable identifier that persists across the server-client boundary.

Client-Safe Transformation and Telemetry

Before reaching the client, the toClientError function (also in src/server/lib/errors.ts) strips internal details unless the code appears in CLIENT_DETAIL_ERROR_CODES (currently only AUTH_CONFIG_MISSING). For reportable errors—determined by shouldCaptureAppErrorCode—the middleware invokes captureServerError in src/server/lib/posthog.ts to record the incident in PostHog or your configured analytics provider. Validation errors are intentionally excluded from telemetry to reduce noise. The middleware simultaneously outputs the stack trace via console.error, accessible via wrangler tail for Cloudflare deployments or docker logs for self-hosted instances.

Common Open-SEO Error Categories and Diagnostic Steps

Understanding the five primary error categories helps you apply the correct fix without unnecessary debugging.

Validation Errors (VALIDATION_ERROR): These occur when user input fails schema checks, such as missing domains or malformed URLs. The codebase throws these in src/server/lib/domainUtils.ts (via normalizeDomainInput) and various feature service files. To resolve, verify the request payload matches the expected schema and use the client helper getErrorCode to display friendly messages.

Auth Configuration Errors (AUTH_CONFIG_MISSING): This code indicates missing or incorrect environment variables like TEAM_DOMAIN, CLOUDFLARE_ACCESS_TOKEN, or Better-Auth settings. Originating in src/middleware/ensure-user/cloudflareAccess.ts and src/server/mcp/oauth-provider.ts, these errors expose detailed messages to the client (unlike other codes). Check your .env.* files against docs/SELF_HOSTING_DOCKER.md to ensure all required keys are present.

Rate Limiting and Quota Errors (RATE_LIMITED, INSUFFICIENT_CREDITS): These surface when DataForSEO quotas exhaust or Cloudflare rate-limits trigger. The DataForSEO client in src/server/lib/dataforseo/client.ts emits these codes. Review your DataForSEO usage dashboard to confirm credit availability, or implement throttling to reduce request frequency.

Upstream Failures (UPSTREAM_UNAVAILABLE, DATAFORSEO_AUTH_FAILED): When the DataForSEO API is down or authentication fails, these codes appear. Verify your DATAFORSEO_API_KEY is the base64-encoded string of login:password and test the endpoint with a direct curl command to isolate connectivity issues.

Internal Server Errors (INTERNAL_ERROR): Uncaught exceptions or bugs in business logic trigger this catch-all code. Any file throwing generic errors outside the AppError classification will result in this response. Check the stack trace in Cloudflare or Docker logs to locate the originating file, then wrap the suspect code in try/catch blocks to improve error handling.

Step-by-Step Troubleshooting Workflow for Open-SEO

Follow this systematic approach to resolve errors efficiently:

  1. Capture the error code on the client: Import getErrorCode and getStandardErrorMessage from @/client/lib/error-messages.ts to extract the machine-readable identifier and user-friendly description from the caught error.

  2. Check runtime logs: For Cloudflare Workers, execute wrangler tail and search for lines containing server.function error:. For Docker deployments, run docker logs <container> to view the same console.error output from the middleware.

  3. Locate the throwing code: Use grep to search the repository for the specific error code, such as grep -R "new AppError(\"VALIDATION_ERROR\"". Common entry points include src/server/lib/domainUtils.ts, src/server/lib/dataforseo/client.ts, and feature service files in src/server/features/*/services/*.ts.

  4. Validate the request payload: Ensure required fields are present before the code reaches DataForSEO API calls. Many VALIDATION_ERROR instances originate in domain normalization checks that reject malformed hosts.

  5. Fix configuration issues: For AUTH_CONFIG_MISSING, verify environment variables including TEAM_DOMAIN, CLOUDFLARE_ACCESS_TOKEN, and CLOUDFLARE_TURNSTILE_SITE_KEY against the self-hosting documentation.

  6. Confirm upstream health: When encountering UPSTREAM_UNAVAILABLE, check the DataForSEO status page and validate your API credentials with a direct HTTP request to their endpoint.

  7. Rerun and verify: After applying fixes, repeat step one. If the client receives a successful response without throwing, the issue is resolved.

Code Examples for Handling Open-SEO Errors

Client-Side Error Handling Pattern

Use this pattern in your frontend to gracefully handle Open-SEO failures:

import { getErrorCode, getStandardErrorMessage } from "@/client/lib/error-messages";

async function runAudit(projectId: string) {
  try {
    const resp = await fetch(`/api/audit?projectId=${projectId}`);
    if (!resp.ok) throw await resp.json();
    // Handle successful audit start...
  } catch (e) {
    const code = getErrorCode(e);
    alert(getStandardErrorMessage(e));
    console.debug("Audit start failed – code:", code);
  }
}

Server-Side Validation Wrapper

Implement consistent validation by throwing AppError instances:

import { AppError } from "@/server/lib/errors";

export function validateDomain(input: string) {
  if (!input) {
    throw new AppError("VALIDATION_ERROR", "Domain is required");
  }
  // Additional validation logic...
}

Adding a Custom Error Code

Extend the error system for domain-specific failures:

  1. Add the code to src/shared/error-codes.ts:
"MY_NEW_CODE",
  1. Add the user-facing message to src/client/lib/error-messages.ts:
MY_NEW_CODE: "Something specific went wrong – please contact support.",
  1. Throw the error in your server logic:
throw new AppError("MY_NEW_CODE", "Details...");

Summary

Frequently Asked Questions

How do I identify which error code Open-SEO returned?

Import getErrorCode from @/client/lib/error-messages.ts and pass the caught error object to it. This function extracts the machine-readable code (e.g., VALIDATION_ERROR) from the server response, allowing you to implement conditional logic or display specific UI messages based on the failure type.

Why am I seeing AUTH_CONFIG_MISSING errors?

This code indicates missing required environment variables such as TEAM_DOMAIN, CLOUDFLARE_ACCESS_TOKEN, or Better-Auth configuration keys. Unlike other Open-SEO errors, this code exposes detailed diagnostic messages to the client. Verify your environment files against the requirements listed in docs/SELF_HOSTING_DOCKER.md and ensure all variables are loaded before the server starts.

How can I view detailed error logs for Open-SEO?

For Cloudflare Worker deployments, use the wrangler tail command to stream logs in real-time and search for entries containing server.function error:. For Docker or self-hosted instances, run docker logs <container_name> to view stdout output. The errorHandlingMiddleware automatically prints stack traces via console.error for every caught exception.

What's the difference between VALIDATION_ERROR and INTERNAL_ERROR?

VALIDATION_ERROR indicates the request failed input validation checks (such as malformed domains or missing required fields) and typically originates in utility functions like src/server/lib/domainUtils.ts. INTERNAL_ERROR represents uncaught exceptions or bugs in business logic that escaped explicit error handling. Validation errors are not reported to PostHog telemetry to avoid dashboard noise, while internal errors are always captured if telemetry is enabled.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →