rohitg00/ai-engineering-from-scratch · error · ValueError
duplicate fixture id
Error message
duplicate fixture id: {f.id} What it means
A corpus-integrity check inside Taxonomy.validate: while walking every fixture to tally per-category counts, the validator tracks ids already seen and rejects the corpus when two fixtures share the same id, since downstream trigram lookups and per-category metrics key on that id. It fires when load_fixtures or a hand-built fixture list contains a duplicated entry — a data-authoring error, not a runtime condition.
Solutions
- Rename one of the colliding fixture ids to a unique value
- Use a dict keyed by id when authoring so duplicates cannot slip in
- Check the CSV for copy-pasted rows
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at phases/19-capstone-projects/82-jailbreak-taxonomy/code/main.py:104 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/958820e3fe76ec79.
Report an issue: GitHub.
Appendix: source
Thrown at phases/19-capstone-projects/82-jailbreak-taxonomy/code/main.py:104
)
)
self._grams = [(_trigrams(f.prompt), f) for f in self._records]
self.validate()
@classmethod
def from_default(cls) -> "Taxonomy":
return cls(load_fixtures())
def validate(self) -> None:
if not self._records:
raise ValueError("empty fixture corpus")
seen_ids: set[str] = set()
per_cat: defaultdict[str, int] = defaultdict(int)
for f in self._records:
if not f.prompt.strip():
raise ValueError(f"fixture {f.id} has empty prompt")
if f.id in seen_ids:
raise ValueError(f"duplicate fixture id: {f.id}")
seen_ids.add(f.id)
lo, hi = SEVERITY_RANGE
if not (lo <= f.severity <= hi):
raise ValueError(f"fixture {f.id} severity {f.severity} out of {SEVERITY_RANGE}")
if f.category not in CATEGORIES:
raise ValueError(f"fixture {f.id} unknown category {f.category}")
per_cat[f.category] += 1
for cat in CATEGORIES:
if per_cat[cat] < MIN_PER_CATEGORY:
raise ValueError(f"category {cat} has {per_cat[cat]} fixtures, need >= {MIN_PER_CATEGORY}")
def all(self) -> list[Fixture]:
return list(self._records)
def by_category(self) -> dict[str, list[Fixture]]:
grouped: dict[str, list[Fixture]] = {c: [] for c in CATEGORIES}
for f in self._records:
grouped[f.category].append(f)View on GitHub (pinned to 39ea8a1c6d)