Conversation
… error
An unverified DataForSEO account answers every data endpoint with a 200
whose envelope carries status_code 40104 ("Please verify your account
before using the API") and no task. That is not an HTTP 401, so core.ts's
auth mapping never fires, and the section classifiers are path-scoped, so
Labs and Keywords Data calls fell through to INTERNAL_ERROR — rendering as
"An unexpected error occurred. Please check server logs and try again."
while the actionable sentence was discarded. The Worker log kept only a
stack with no message, so the server logs that message points at did not
contain the reason either.
Classify the refusal on the envelope as DATAFORSEO_AUTH_FAILED carrying
DataForSEO's own status_message, and allow that code's detail through
toClientError so the user reads the fix. The code also aborts local-SEO
grids mid-run, which is correct here: every remaining point would be
refused identically.
Matched by exact code rather than the 401xx prefix — DataForSEO reuses
that range for task-level search-engine failures (40101, 40103) that
UPSTREAM_FAILURE_STATUS_CODES already classifies and that mean the
opposite.
Closes every-app#305
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZja8vK2mx6gf2BfZMAXDj
ywwenjin163
pushed a commit
to ywwenjin163/open-seo
that referenced
this pull request
Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #305.
Problem
A DataForSEO account that has not completed verification answers every data endpoint with an HTTP 200 whose envelope carries:
{ "status_code": 40104, "status_message": "Please verify your account before using the API. …", "tasks": null, "tasks_count": 0, "cost": 0 }That reaches the user as "An unexpected error occurred. Please check server logs and try again."
Three things line up to hide the cause:
core.ts's auth mapping never sees it;/backlinks/, AI Optimization), so/dataforseo_labs/and/keywords_data/get no classification and fall through toINTERNAL_ERROR;Diagnosing it currently means reproducing the API call by hand outside the app. It is a day-one blocker for new self-hosters, because DataForSEO issues working credentials before verification and
/v3/appendix/user_datasucceeds in that state — the key validates while every data endpoint refuses.Change
DATAFORSEO_AUTH_FAILED, carrying DataForSEO's ownstatus_message.DATAFORSEO_AUTH_FAILEDtoCLIENT_DETAIL_ERROR_CODESso that message reaches the user, matching the existing rationale for that set — setup problems whose text names the fix, where a generic card makes every misconfiguration look the same. The static fallback inerror-messages.tsonly guesses at a malformed key, so the provider's sentence is strictly better guidance.console.warnthe refusal, for the reason the neighbouring upstream branch already documents: the error handlers log only what they capture, so this is the sole record of the message.Notes for review
Matched by exact code, not by 401xx prefix. My first attempt used the range and your existing test caught it: DataForSEO reuses that range for task-level search-engine failures —
40101"Internal SE Server Error" and40103"Task execution failed" are already inUPSTREAM_FAILURE_STATUS_CODESand mean the opposite (retry, don't go fix the account). The set starts at40104alone and is easy to extend.Envelope only, not the task ladder. Account refusals arrive with no task at all, and the 401xx collision above lives entirely at task level, so classifying only the envelope keeps the two apart.
Ordering. The check sits before the charged-task branch, per that module's existing instruction: "Do not throw this for access / balance failures; classify those first even when DataForSEO includes billing metadata on the failed task." These refusals cost $0.
Reusing
DATAFORSEO_AUTH_FAILEDrather than adding a code also gets the right local-SEO behaviour for free:GRID_ABORT_ERROR_CODESalready treats it as "every remaining call would fail the same way", which is exactly true of an unverified account.Deliberately out of scope: balance failures (
40200) on paths without a section classifier still surface asINTERNAL_ERROR. Fixing those means either a generic billing code or unscoping the two existing section-specific ones — a design call I did not want to make inside a bug fix. Happy to follow up if you have a preference.Verification
pnpm ci:checkpasses.pnpm test: the one failure (oauth-provider.test.ts, "binds tokens and protected-resource metadata to the canonical MCP URL") reproduces identically on a cleanorigin/mainand passes in isolation — pre-existing and unrelated.🤖 Generated with Claude Code
https://claude.ai/code/session_01EZja8vK2mx6gf2BfZMAXDj