How OpenSEO Handles Error Codes and Billing Classification
OpenSEO centralizes error handling in a Zod-validated schema at src/shared/error-codes.ts and classifies DataForSEO billing failures using specialized classifiers in src/server/lib/dataforseoBillingClassification.ts, converting external HTTP 402 responses into distinct internal codes like BACKLINKS_BILLING_ISSUE and AI_SEARCH_BILLING_ISSUE.
OpenSEO, from the repository every-app/open-seo, implements a type-safe error architecture that distinguishes between system failures and user-facing billing issues. Understanding how OpenSEO handles error codes and billing classification reveals a robust approach to managing external API degradation and payment-related failures. The system combines a closed-set error enumeration with per-API billing classifiers to ensure accurate error routing and monitoring.
Centralized Error Code Management with Zod
The foundation of OpenSEO's error handling lies in src/shared/error-codes.ts, which defines a strict, closed-set of error identifiers using Zod validation. This approach ensures that every error passed through the system conforms to a predefined schema, enabling type-safe error handling across both client and server boundaries.
The Error Code Schema
The errorCodeSchema uses Zod's enum validation to establish the canonical set of valid errors. This schema is exported as a TypeScript type called ErrorCode for use throughout the application:
export const errorCodeSchema = z.enum([
"UNAUTHENTICATED",
"AUTH_CONFIG_MISSING",
"PAYMENT_REQUIRED",
"INSUFFICIENT_CREDITS",
"FORBIDDEN",
"NOT_FOUND",
"AUDIT_CAPACITY_REACHED",
"AUDIT_PAGE_LIMIT_EXCEEDED",
"AUDIT_ALREADY_RUNNING",
"VALIDATION_ERROR",
"CRAWL_TARGET_BLOCKED",
"BACKLINKS_BILLING_ISSUE",
"AI_SEARCH_BILLING_ISSUE",
"DATAFORSEO_AUTH_FAILED",
"RATE_LIMITED",
"UPSTREAM_UNAVAILABLE",
"CONFLICT",
"INTERNAL_ERROR",
] as const);
Filtering Non-Reportable Errors
Not all errors warrant monitoring service alerts. OpenSEO maintains a set of non-reportable error codes (such as authentication failures or insufficient credits) that should not clutter error-tracking dashboards. The helper function shouldCaptureAppErrorCode implements this filtering logic:
export function shouldCaptureAppErrorCode(
code: ErrorCode | null | undefined,
): boolean {
return code == null || !NON_REPORTABLE_ERROR_CODES.has(code);
}
When this function returns false, the error is excluded from external capture services while still being available for user-facing error display.
Billing Classification for DataForSEO Integrations
When interacting with external DataForSEO APIs, OpenSEO must translate ambiguous HTTP responses—particularly HTTP 402 status codes—into actionable internal error codes. The module src/server/lib/dataforseoBillingClassification.ts provides a factory function that creates specialized classifiers for different API sections.
The Billing Classifier Factory
The createDataforseoBillingClassifier function generates type-safe classifiers that inspect response status codes and message content for billing-related signals. It looks for specific billing status codes (the HTTP 402 family) and billing signals (keywords like "insufficient funds" or "balance is too low"):
export function createDataforseoBillingClassifier(config: {
pathPrefix: string;
billingIssueCode: ErrorCode;
billingIssueMessage: string;
}): DataforseoBillingClassifier {
return (status, details, path) => {
if (!path.includes(config.pathPrefix)) return null;
const text = details.toLowerCase();
const matchesBillingStatus = status != null && BILLING_STATUS_CODES.has(status);
const matchesBillingText = BILLING_SIGNALS.some((signal) => text.includes(signal));
if (matchesBillingStatus || matchesBillingText) {
return new AppError(config.billingIssueCode, config.billingIssueMessage);
}
return null;
};
}
Per-API Billing Implementations
Each DataForSEO API section (Backlinks, AI Search, etc.) instantiates its own classifier with specific configuration. In src/server/lib/dataforseo/backlinks.ts, the classifier targets the /backlinks path prefix:
const classifyBacklinksError = createDataforseoBillingClassifier({
pathPrefix: "/backlinks",
billingIssueCode: "BACKLINKS_BILLING_ISSUE",
billingIssueMessage: "Your DataForSEO balance is too low for Backlinks requests.",
});
Similarly, src/server/lib/dataforseo/ai.ts configures classification for AI Search endpoints:
const classifyAiSearchError = createDataforseoBillingClassifier({
pathPrefix: "/ai-search",
billingIssueCode: "AI_SEARCH_BILLING_ISSUE",
billingIssueMessage: "Your DataForSEO balance is too low for AI Search requests.",
});
When a DataForSEO request fails, the corresponding classifier runs first. If it detects a billing problem, it returns an AppError with the appropriate internal error code. The generic error-handling middleware in src/middleware/errorHandling.ts then translates these codes to user-visible messages or redirects to the billing UI.
Credit to USD Conversion and Billing Logic
Beyond error classification, OpenSEO manages usage-based billing through src/shared/billing.ts. This module defines the credit-to-currency conversion rate and applies platform markup for hosted deployments:
export const AUTUMN_SEO_DATA_CREDITS_PER_USD = 1000;
export function roundUsdForBilling(value: number) {
return Math.round(value * 100000) / 100000;
}
export function autumnSeoDataCreditsToUsd(credits: number) {
return credits / AUTUMN_SEO_DATA_CREDITS_PER_USD;
}
/** Apply the platform markup before billing the hosted customer */
export function applyBillingMarkupUsd(rawUsd: number) {
return roundUsdForBilling(rawUsd * SEO_DATA_COST_MARKUP);
}
These utilities ensure that cost displays match actual charge amounts, while self-hosted deployments can skip the markup step entirely.
Summary
- OpenSEO defines a strict error code enumeration in
src/shared/error-codes.tsusing Zod validation to ensure type safety across the application. - The
shouldCaptureAppErrorCodefunction filters non-reportable errors (authentication, insufficient credits) to prevent noise in error tracking services. - Billing classification uses factory functions in
src/server/lib/dataforseoBillingClassification.tsto detect HTTP 402 responses and specific keywords like "insufficient funds" from DataForSEO APIs. - Distinct error codes (
BACKLINKS_BILLING_ISSUE,AI_SEARCH_BILLING_ISSUE) allow the middleware insrc/middleware/errorHandling.tsto route users to appropriate billing UI flows. - Credit-to-USD conversion utilities in
src/shared/billing.tshandle platform markup calculations for accurate billing displays.
Frequently Asked Questions
What is the complete list of error codes defined in OpenSEO?
The errorCodeSchema in src/shared/error-codes.ts defines 18 distinct error codes including UNAUTHENTICATED, PAYMENT_REQUIRED, INSUFFICIENT_CREDITS, AUDIT_CAPACITY_REACHED, BACKLINKS_BILLING_ISSUE, AI_SEARCH_BILLING_ISSUE, and UPSTREAM_UNAVAILABLE. These cover authentication failures, resource limits, billing issues, and upstream service unavailability.
How does OpenSEO prevent billing-related errors from cluttering error tracking dashboards?
The shouldCaptureAppErrorCode function checks incoming error codes against the NON_REPORTABLE_ERROR_CODES set. When errors like UNAUTHENTICATED or INSUFFICIENT_CREDITS occur, the function returns false, preventing them from being sent to external monitoring services while still allowing user-facing error display.
What triggers the BACKLINKS_BILLING_ISSUE error code?
This error occurs when the DataForSEO Backlinks API returns an HTTP 402 status code or response text containing keywords like "insufficient funds" or "balance is too low". The classifyBacklinksError function in src/server/lib/dataforseo/backlinks.ts detects these signals and converts them to the internal BACKLINKS_BILLING_ISSUE code.
How does OpenSEO convert usage credits to billing amounts?
The src/shared/billing.ts module defines AUTUMN_SEO_DATA_CREDITS_PER_USD (1000 credits per USD) and provides autumnSeoDataCreditsToUsd for conversion. For hosted deployments, applyBillingMarkupUsd multiplies the raw cost by the platform markup factor before rounding to five decimal places for precise billing.
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 →