mvanhorn/last30days-skill · error · SourceRunError

All X backends failed — {last_error}

Error message

All X backends failed — {last_error}

What it means

SourceRunError raised after the X backend chain is exhausted: every backend (bird, ScrapeCreators, grok, ...) either returned no items or errored, and at least one recorded an error (last_error). The failure state is classified — bird_x.classify_run_failure for 'bird:'-prefixed errors, otherwise http.classify_failure — so callers can distinguish auth, rate-limit, and network classes.

Source

Thrown at skills/last30days/scripts/lib/pipeline.py:4265

                    state = http.classify_failure(message=err)
                    return items, _outcome_artifact(
                        state,
                        f"X returned {len(items)} items but also errored: {err}",
                    )
                # No auth issues and no prior errors - proceed to judge-retry
                used_backend = backend
                break
            if err:
                last_error = f"{backend}: {err}"
                print(f"[X] backend '{backend}' failed ({err}); trying next", file=sys.stderr)

        if not items and last_error:
            state = (
                bird_x.classify_run_failure(last_error)
                if last_error.startswith("bird:")
                else http.classify_failure(message=last_error)
            )
            raise SourceRunError(f"All X backends failed — {last_error}", state)

        # Retrieve-judge-retry: judge corpus and retry if off-topic flood.
        # Skip retry on quick/mock (same as Phase 2).
        artifact = {}
        if items and depth != "quick" and not mock:
            items_for_judge = [
                {"author_handle": it.get("author_handle", ""), "text": it.get("text", "")}
                for it in items
            ]
            if x_judge.should_retry_x_search(items_for_judge, x_query, ranking_query=ranking_query, depth=depth):
                # Retry with cleaned query (1 retry, ≤2 extra grok calls)
                # Strip noise words but preserve all significant terms to avoid
                # losing disambiguating terms (e.g., "react server components")
                core_tokens = query.extract_core_subject(x_query)
                retry_query = core_tokens or x_query
                print(f"[X] corpus off-topic; retrying with '{retry_query}'", file=sys.stderr)

                if used_backend:

View on GitHub (pinned to c7460f6114)

Solutions

  1. Read the error state: AUTH_FAILED → re-auth the failing backend (device flow / new key); RATE_LIMITED → back off and retry later.
  2. Verify the ScrapeCreators key with a minimal API call (check status code, never print the key).
  3. Pin a known-good backend at runtime (runtime.x_search_backend) to skip a broken primary.
  4. Retry the run after transient outages; if persistent, drop 'x' from sources to still get results elsewhere.

Example fix

# before
items, meta = fetch_x(subquery, ...)

# after
try:
    items, meta = fetch_x(subquery, ...)
except SourceRunError as exc:
    if "AUTH" in str(exc.state):
        refresh_x_credentials()
        items, meta = fetch_x(subquery, ...)
    else:
        raise
Defensive patterns

Strategy: retry

Try / catch

try:
    items, meta = fetch_x(...)
except SourceRunError as exc:
    state = str(exc.state)
    if "RATE" in state:
        time.sleep(60)
        items, meta = fetch_x(...)
    elif "AUTH" in state:
        refresh_x_credentials()
        raise  # caller must re-run with fixed credentials
    else:
        raise

Prevention

When it happens

Trigger: Iterating the chain via _fetch_x_backend: each backend returns (items, err); a backend with items breaks the loop. If no backend yields items and last_error is non-empty (e.g. 'bird: token revoked' then 'scrapecreators: 429'), the SourceRunError is raised with the last error text.

Common situations: Revoked grok OAuth token plus exhausted ScrapeCreators quota; sustained rate limiting across all backends during heavy usage; upstream API outage; malformed query strings rejected by every backend.

Related errors


AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15). Data as JSON: /api/errors/6284596085325094. Report an issue: GitHub.