mvanhorn/last30days-skill · error · ValueError
No listing sources are available for {normalized_domain!r}
Error message
No listing sources are available for {normalized_domain!r} What it means
Same guard as the global branch, but for a non-empty domain: build_discovery_plan intersects DISCOVERY_SOURCE_ORDER with available_sources and raises when the intersection is empty. Unlike the global branch, 'x' is NOT discarded here, but 'x' is also not in DISCOVERY_SOURCE_ORDER, so passing only non-listing sources still triggers it. The domain is echoed with !r for easy debugging.
Source
Thrown at skills/last30days/scripts/lib/planner.py:76
seen_subreddits: set[str] = set()
resolved_subreddits: list[str] = []
for subreddit in candidate_subreddits:
normalized_subreddit = subreddit.removeprefix("r/").strip()
key = normalized_subreddit.lower()
if not normalized_subreddit or key in seen_subreddits:
continue
seen_subreddits.add(key)
resolved_subreddits.append(normalized_subreddit)
# The curated map intentionally stays small. Keep discovery's keyless floor
# for uncategorized domains by sweeping r/all and applying domain relevance
# during normalization instead of inventing a second category resolver.
if not resolved_subreddits:
resolved_subreddits = ["all"]
allowed = set(DISCOVERY_SOURCE_ORDER if available_sources is None else available_sources)
sources = [source for source in DISCOVERY_SOURCE_ORDER if source in allowed]
if not sources:
raise ValueError(f"No listing sources are available for {normalized_domain!r}")
return schema.DiscoveryPlan(
domain=normalized_domain,
category=category,
subreddits=resolved_subreddits,
sources=sources,
)
ALLOWED_INTENTS = {
"factual",
"product",
"concept",
"opinion",
"how_to",
"comparison",
"breaking_news",
"prediction",
}View on GitHub (pinned to c7460f6114)
Solutions
- Pass at least one listing source (reddit/hackernews/digg) in available_sources.
- Use run_discover instead of the planner directly — it computes availability and filters requested sources correctly.
- If this surfaces from the pipeline path, treat it as 'no listing source currently available' and fix credentials/PATH for digg if that was the only one requested.
Example fix
# before
plan = planner.build_discovery_plan("rust compilers", available_sources=[])
# after
plan = planner.build_discovery_plan("rust compilers", available_sources=["reddit", "hackernews", "digg"]) Defensive patterns
Strategy: validation
Validate before calling
LISTING = {"reddit", "hackernews", "digg"}
if not (set(available_sources or []) & LISTING):
available_sources = list(LISTING) # or raise explicitly
plan = planner.build_discovery_plan(domain, available_sources=available_sources) Try / catch
try:
plan = planner.build_discovery_plan(domain, available_sources=srcs)
except ValueError as exc:
if "No listing sources" in str(exc):
plan = planner.build_discovery_plan(domain, available_sources=["reddit"])
else:
raise Prevention
- Prefer run_discovery over direct planner calls; it computes availability for you.
- All three listing sources work without keys, so an empty intersection almost always means a caller bug, not missing credentials.
When it happens
Trigger: build_discovery_plan(domain='example topic', available_sources=['youtube']) or available_sources=[] — the ordered intersection [s for s in DISCOVERY_SOURCE_ORDER if s in allowed] is empty and the ValueError fires with the domain repr.
Common situations: Custom callers/tests passing restricted or empty available_sources; configs where every listing source was filtered out upstream (e.g. all failed availability checks); passing search-style sources to the discovery planner.
Related errors
- No listing sources are available for global trending
- Discovery supports listing sources only: reddit, hackernews,
- subqueries[{index}].sources must be a non-empty string array
- Unknown search source in {flag_name}: {source}
- {flag_name} requires at least one source.
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/f2bcb6b692a1dd0f.
Report an issue: GitHub.