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:
-
Capture the error code on the client: Import
getErrorCodeandgetStandardErrorMessagefrom@/client/lib/error-messages.tsto extract the machine-readable identifier and user-friendly description from the caught error. -
Check runtime logs: For Cloudflare Workers, execute
wrangler tailand search for lines containingserver.function error:. For Docker deployments, rundocker logs <container>to view the sameconsole.erroroutput from the middleware. -
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 includesrc/server/lib/domainUtils.ts,src/server/lib/dataforseo/client.ts, and feature service files insrc/server/features/*/services/*.ts. -
Validate the request payload: Ensure required fields are present before the code reaches DataForSEO API calls. Many
VALIDATION_ERRORinstances originate in domain normalization checks that reject malformed hosts. -
Fix configuration issues: For
AUTH_CONFIG_MISSING, verify environment variables includingTEAM_DOMAIN,CLOUDFLARE_ACCESS_TOKEN, andCLOUDFLARE_TURNSTILE_SITE_KEYagainst the self-hosting documentation. -
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. -
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:
- Add the code to
src/shared/error-codes.ts:
"MY_NEW_CODE",
- Add the user-facing message to
src/client/lib/error-messages.ts:
MY_NEW_CODE: "Something specific went wrong – please contact support.",
- Throw the error in your server logic:
throw new AppError("MY_NEW_CODE", "Details...");
Summary
- Open-SEO uses a centralized
errorHandlingMiddlewareinsrc/middleware/errorHandling.tsto catch and normalize all exceptions. - Errors are classified using typed codes defined in
src/shared/error-codes.tsand transported via theAppErrorclass insrc/server/lib/errors.ts. - Client-side utilities in
src/client/lib/error-messages.tstranslate codes into user-friendly messages. - Validation errors typically originate in
src/server/lib/domainUtils.ts, while auth errors stem fromsrc/middleware/ensure-user/cloudflareAccess.ts. - View detailed stack traces using
wrangler tailfor Cloudflare ordocker logsfor self-hosted deployments. - Only
AUTH_CONFIG_MISSINGexposes detailed error messages to clients; other codes return sanitized responses for security.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →