mvanhorn/last30days-skill · warning · DrillTargetError

No cluster matched {target!r}. Available clusters: {candidat

Error message

No cluster matched {target!r}. Available clusters: {candidates}

What it means

DrillTargetError (a ValueError subclass) from resolve_drill_clusters when the target parses as a 1-based cluster index (e.g. '3', 'cluster 3', '#3') but the number is outside 1..len(report.clusters). The error carries the target and the report's clusters so its message can list available candidates.

Source

Thrown at skills/last30days/scripts/lib/planner.py:245

def _drill_cluster_text(report: schema.Report, cluster: schema.Cluster) -> str:
    candidates = {candidate.candidate_id: candidate for candidate in report.ranked_candidates}
    parts = [cluster.title]
    for candidate_id in cluster.candidate_ids:
        candidate = candidates.get(candidate_id)
        if candidate:
            parts.extend((candidate.title, candidate.snippet))
    return " ".join(part for part in parts if part)


def resolve_drill_clusters(report: schema.Report, target: str) -> list[schema.Cluster]:
    """Resolve a 1-based cluster index or fuzzy title/entity description."""
    cleaned = target.strip()
    numeric = re.fullmatch(r"(?:cluster\s*)?#?(\d+)", cleaned, flags=re.IGNORECASE)
    if numeric:
        index = int(numeric.group(1))
        if 1 <= index <= len(report.clusters):
            return [report.clusters[index - 1]]
        raise DrillTargetError(target, report.clusters)

    target_entities = entity_extract.extract_text_entities(cleaned)
    scored: list[tuple[float, schema.Cluster]] = []
    for cluster in report.clusters:
        cluster_text = _drill_cluster_text(report, cluster)
        title_score = relevance.token_overlap_relevance(cleaned, cluster.title)
        body_score = relevance.token_overlap_relevance(cleaned, cluster_text)
        entity_score = entity_extract.entity_overlap(
            target_entities,
            entity_extract.extract_text_entities(cluster_text),
        )
        score = max(title_score, (0.75 * body_score) + (0.25 * entity_score))
        scored.append((score, cluster))

    scored.sort(key=lambda entry: entry[0], reverse=True)
    if not scored or scored[0][0] < 0.35:
        raise DrillTargetError(target, report.clusters)
    return [scored[0][1]]

View on GitHub (pinned to c7460f6114)

Solutions

  1. Use an index between 1 and len(report.clusters) — clusters are 1-based.
  2. Or pass the cluster title / entity description instead of a number; fuzzy matching will resolve it.
  3. Re-check the current report's cluster count before drilling.

Example fix

# before
plan = build_drill_plan(report, target="7")  # report has 4 clusters

# after
plan = build_drill_plan(report, target=str(len(report.clusters)))
# or drill by title:
plan = build_drill_plan(report, target="AI agent frameworks")
Defensive patterns

Strategy: validation

Validate before calling

import re
m = re.fullmatch(r"(?:cluster\s*)?#?(\d+)", target.strip(), re.IGNORECASE)
if m and not (1 <= int(m.group(1)) <= len(report.clusters)):
    raise SystemExit(f"cluster index must be 1..{len(report.clusters)}")

Try / catch

try:
    plan = build_drill_plan(report, target=t)
except DrillTargetError as exc:
    print(f"valid targets: 1..{len(report.clusters)} or cluster titles")
    raise

Prevention

When it happens

Trigger: Calling build_drill_plan / resolve_drill_clusters with target='5' on a report whose clusters list has fewer than 5 entries; target='0' (index is 1-based, so 0 never matches); large indices after re-running with shallower depth produced fewer clusters.

Common situations: User asks to drill into cluster 7 from a previous report but the current report has 4 clusters; stale cluster numbers quoted from an earlier session; off-by-one from assuming 0-based indexing.

Related errors


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