Skip to content

Stop reporting config failures as dead grants or internal errors - #349

Open
VodouAI wants to merge 1 commit into
every-app:mainfrom
VodouAI:fix/error-classification
Open

VodouAI wants to merge 1 commit into
every-app:mainfrom
VodouAI:fix/error-classification

Conversation

@VodouAI

@VodouAI VodouAI commented Sep 20, 2026 •

Copy link
Copy Markdown

Three failures that told the operator the wrong thing, all found while self-hosting.

Search Console 403 read as a revoked grant

isExpectedGrantFailure grouped 403 with 401, so any 403 rendered as "Connection expired" with a Reconnect button — and no log line, since expected grant failures are deliberately not reported.

The most common 403 is the Search Console API not being enabled in the Cloud project behind GOOGLE_CLIENT_ID. The grant is healthy, reconnecting changes nothing, and the UI's only suggested remedy is the one action that cannot work. On a fresh self-host this is an hour of deleting and re-linking an account that was fine the whole time, with nothing in the logs to say otherwise.

403 now surfaces as a load failure and stays reportable, so the reason reaches the logs. This matches GA4, which already classified only 401 (Ga4Service.requiresReconnect) — GSC was the outlier. messageForStatus also splits 401 from 403 and names the Cloud console when Google reports accessNotConfigured or SERVICE_DISABLED.

DataForSEO 403 read as an internal error

An unverified DataForSEO account answers every call with 403 and status_code: 40104, "Please verify your account before using the API." Only 401 mapped to DATAFORSEO_AUTH_FAILED, so this fell through to INTERNAL_ERROR and reached the user as "an unexpected error occurred."

403 now joins 401. Beyond the message, DATAFORSEO_AUTH_FAILED is already in GRID_ABORT_ERROR_CODES, so a local-SEO rank grid aborts on the first failure instead of firing 24 more doomed, billable calls.

get_serp_results failures left no trace

The tool degrades per keyword rather than failing the batch — good behavior — but the caught error never reaches the instrumentation wrapper, so nothing lands in the logs. A provider outage, an account-level rejection, or a call DataForSEO already billed is invisible server-side. I only found the 403s above because the agent's transcript mentioned them; the server had recorded nothing.

Failures now warn before the tool degrades. The degradation behavior is unchanged.

Notes

  • docs/SELF_HOSTING_GOOGLE_SEARCH_CONSOLE.md gains a troubleshooting entry for this, including the Google account · <digits> symptom that appears when the email lookup fails alongside everything else.
  • Tests: the old GscApiError(403) reconnect case is now the 401 case, plus one new test per invariant.
  • 290 tests pass across src/server/features/gsc, src/server/lib/dataforseo, and src/server/mcp; prettier and oxlint clean.

A 403 from Google means the Search Console API is not enabled in the
Cloud project behind the OAuth client at least as often as it means a
permission problem, and neither is fixable by reconnecting. Classifying
it with 401 showed a healthy grant as "Connection expired" and hid the
reason from the logs, so the only remedy the UI offers — remove the
account and link it again — could never work. GSC now matches GA4: 401
and a token-mint failure prompt a reconnect, 403 surfaces as a load
failure and stays reportable, and the 403 message names the Cloud
console when Google reports accessNotConfigured or SERVICE_DISABLED.

DataForSEO answers an unverified account with 403 and status_code
40104. As INTERNAL_ERROR that reached the user as "an unexpected error
occurred" and let a local-SEO rank grid fire 24 more doomed, billable
calls; it now joins 401 as DATAFORSEO_AUTH_FAILED, which
GRID_ABORT_ERROR_CODES already aborts on.

get_serp_results degrades per keyword rather than failing the batch, so
its throws never reach the instrumentation wrapper and left no
server-side trace of a provider outage or a billed-but-failed call.
Those failures now warn before the tool degrades.

Found while self-hosting: a disabled Search Console API cost an hour of
disconnecting and reconnecting a grant that was healthy the whole time.
@VodouAI
VodouAI force-pushed the fix/error-classification branch from ad817bb to f64b191 Compare September 20, 2026 06:26
TamerHammouda pushed a commit to TamerHammouda/open-seo that referenced this pull request Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant