datawhalechina/hello-agents · error · FileNotFoundError
Incident '{incident_id}' not found. Available: {list_inciden
Error message
Incident '{incident_id}' not found. Available: {list_incidents()} What it means
Raised by load_incident in src/agents/pipeline.py when data/incidents/{incident_id}.json does not exist. The message includes list_incidents() — the stems of every JSON file in data/incidents/ — so it doubles as a directory listing. Note path.exists() follows the literal string; any ID not matching a filename exactly (case, extension, traversal) fails.
Source
Thrown at Co-creation-projects/zjzhou-SREOnCallAgent/src/agents/pipeline.py:26
from src.core.llm_client import HelloAgentsLLM
from src.agents.triage_agent import TriageAgent
from src.agents.investigation_agent import InvestigationAgent
from src.agents.postmortem_agent import PostmortemAgent
DATA_DIR = Path(__file__).resolve().parents[2] / "data"
INCIDENTS_DIR = DATA_DIR / "incidents"
RUNBOOKS_DIR = DATA_DIR / "runbooks"
def list_incidents():
return [p.stem for p in INCIDENTS_DIR.glob("*.json")]
def load_incident(incident_id: str) -> Dict[str, Any]:
path = INCIDENTS_DIR / f"{incident_id}.json"
if not path.exists():
raise FileNotFoundError(
f"Incident '{incident_id}' not found. "
f"Available: {list_incidents()}"
)
with open(path) as f:
return json.load(f)
def run_pipeline(incident_id: str, verbose: bool = True) -> Dict[str, Any]:
"""
Full three-stage SRE pipeline for a given incident ID.
Returns a dict with: incident_id, plan, findings, report
"""
incident = load_incident(incident_id)
llm = HelloAgentsLLM(verbose=verbose)
# Stage 1: Triage — Plan-and-Solve
triage = TriageAgent(llm)View on GitHub (pinned to 606a07d341)
Solutions
- Read the 'Available:' list in the error message and use one of those exact IDs.
- If the incident should exist, check data/incidents/ for the exact filename (case, no .json suffix in the ID).
- Regenerate or restore the incident JSON if the data directory is incomplete.
- When exposing via API, list incidents through the provided list endpoint instead of guessing IDs.
Example fix
# before
result = run_pipeline("INC-999")
# after
from src.agents.pipeline import list_incidents
print(list_incidents()) # ['inc-001', 'inc-002']
result = run_pipeline("inc-001") Defensive patterns
Strategy: validation
Validate before calling
from src.agents.pipeline import list_incidents
AVAILABLE = set(list_incidents())
if incident_id not in AVAILABLE:
raise ValueError(f"unknown incident {incident_id!r}; choose from {sorted(AVAILABLE)}")
result = run_pipeline(incident_id) Type guard
import re
def is_valid_incident_id(v: str) -> bool:
"""Alphanumeric/dash IDs only, no extension, no traversal."""
return bool(re.fullmatch(r"[A-Za-z0-9_-]+", v)) Try / catch
try:
result = run_pipeline(incident_id)
except FileNotFoundError as e:
print(e) # message lists available incidents
incident_id = list_incidents()[0]
result = run_pipeline(incident_id) Prevention
- Always resolve IDs via list_incidents() first instead of hardcoding.
- Normalize casing and strip '.json' from user-supplied IDs before use.
- Ship data/incidents/*.json with the deployment; verify presence in a health check.
- Reject path-like IDs at the API boundary (regex allow-list) to avoid traversal probing.
When it happens
Trigger: Calling run_pipeline('INC-001') when the file is data/incidents/inc-001.json; passing an ID with '.json' appended (produces 'x.json.json'); requesting an incident never created; path traversal like '../secrets' finds nothing and errors the same way.
Common situations: Case-mismatch between API input and filenames; users typing IDs from memory instead of listing available ones; the data directory not cloned/deployed with the repo; ID format changed (INC-42 vs 42) between dataset versions.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/248c3bd6c975295e.
Report an issue: GitHub.