mvanhorn/last30days-skill · error · RuntimeError
No X backend is available.
Error message
No X backend is available.
What it means
RuntimeError raised in the X fetch leg when env.x_backend_chain(config) resolves to an empty chain AND no runtime-pinned backend (runtime.x_search_backend) is set. The chain is built from configured backends (e.g. bird session, ScrapeCreators/grok), so an empty chain means the config has no usable X credential at all. It is raised before any fetch is attempted.
Source
Thrown at skills/last30days/scripts/lib/pipeline.py:4208
f"{public_failure}",
)
return merged, {}
if source == "x":
# Compile X query from raw_topic (like Reddit/YouTube), not planner's
# search_query which may contain operator strings like "Rome Italy".
x_query = raw_topic or topic or subquery.search_query
ranking_query = subquery.ranking_query
# One X source, an ordered chain of interchangeable backends. Try the
# primary; fall through to the next only if it returns nothing or errors.
chain = env.x_backend_chain(config)
# Trust an explicit runtime backend as the primary (already resolved as
# available), keeping the rest of the chain as failover backups.
pinned = runtime.x_search_backend
if pinned:
chain = [pinned] + [b for b in chain if b != pinned]
if not chain:
raise RuntimeError("No X backend is available.")
last_error = ""
items = []
used_backend = None
for i, backend in enumerate(chain):
items, err = _fetch_x_backend(backend, x_query, from_date, to_date, depth, config)
if items:
if i > 0:
print(f"[X] primary backend(s) returned nothing; used fallback '{backend}'", file=sys.stderr)
# Check for auth errors before proceeding to judge-retry
if last_error:
# Fallback succeeded after earlier backend failed. Classify
# the original error: if it was AUTH_FAILED (grok revoked),
# preserve that state so user gets re-login guidance.
prior_state = http.classify_failure(message=last_error)
if prior_state == schema.AUTH_FAILED:
# Keep AUTH_FAILED visible so host shows re-login hint
return items, _outcome_artifact(
schema.AUTH_FAILED,View on GitHub (pinned to c7460f6114)
Solutions
- Set SCRAPECREATORS_API_KEY (onboarding persists it automatically via setup_wizard.write_api_key).
- Re-run the setup wizard / GitHub device-auth flow to restore the bird or grok backend.
- Or exclude 'x' from requested_sources and rely on keyless sources.
- Check env.x_backend_chain(config) returns non-empty before running if you orchestrate configs dynamically.
Example fix
# before
run_pipeline(topic, requested_sources=["x"], config={})
# after
run_pipeline(topic, requested_sources=["x"], config={"SCRAPECREATORS_API_KEY": os.environ["SCRAPECREATORS_API_KEY"]}) Defensive patterns
Strategy: validation
Validate before calling
from skills.last30days.scripts.lib import env
if not env.x_backend_chain(config):
raise SystemExit("no X backend configured: set SCRAPECREATORS_API_KEY or run setup") Try / catch
try:
items, meta = fetch_x(...)
except RuntimeError as exc:
if "No X backend" in str(exc):
sources.remove("x")
items, meta = None, None # continue with remaining sources Prevention
- Complete onboarding once; setup_wizard persists SCRAPECREATORS_API_KEY with 0o600 automatically.
- Assert env.x_backend_chain(config) is non-empty before requesting the x source.
When it happens
Trigger: Calling the pipeline with source 'x' while: no ScrapeCreators key, no bird session file, and X_SEARCH_BACKEND env unset/empty; or every backend in the chain has been disabled via config. pinned is falsy, so chain stays [].
Common situations: Fresh install that skipped onboarding (no GitHub device-auth, no SCRAPECREATORS_API_KEY); expired/removed bird session; env var typos like X_BACKEND instead of the expected names; CI environments with no credentials.
Related errors
- No sources are available for this run.
- All X backends failed — {last_error}
- Gemini selected but no Google API key is configured.
- xAI selected but XAI_API_KEY is not configured.
- OpenRouter selected but OPENROUTER_API_KEY is not configured
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/65922828d819459b.
Report an issue: GitHub.