affaan-m/ECC · error · ValueError

genre has no references

Error message

genre {genre['slug']} has no references

What it means

After iterating a genre's references, run_workflow requires that at least one reference successfully resolved and probed (genre_refs non-empty). Since missing files already raise FileNotFoundError, this fires when a genre dict exists but its 'references' list is empty or absent. Every numbered genre must carry at least one reference video.

Solutions

  1. Add at least one valid reference path to the offending genre's 'references' list
  2. Remove the empty genre from config['genres'] if it is not needed
  3. Log/validate each genre's references before calling run_workflow

Example fix

// before
{'number': 2, 'slug': 'documentary', 'references': []}
// after
{'number': 2, 'slug': 'documentary', 'references': ['/data/refs/doc_reference.mp4']}
Defensive patterns

Strategy: validation

Validate before calling

bad = [g['slug'] for g in config.get('genres', []) if not g.get('references')]
if bad:
    raise ValueError(f'genres without references: {bad}')

Type guard

def all_genres_have_references(config) -> bool:
    return all(bool(g.get('references')) for g in config.get('genres', []))

Try / catch

try:
    run_workflow(config, out_dir)
except ValueError as e:
    if 'has no references' in str(e):
        print('Fill in or remove the empty genre before running')
    else:
        raise

Prevention

When it happens

Trigger: config['genres'] includes a genre entry whose 'references' key is missing, set to [], or only contains falsy/filtered entries.

Common situations: Template config with placeholder genres and no references filled in; a script that appends genres before collecting their reference paths; an edit that accidentally cleared one genre's references.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/48dec5dae4a7c695. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/workflow.py:603

            path = resolve_input(raw_path)
            if not path.is_file():
                raise FileNotFoundError(path)
            measured, source_bytes, source_digest = _stable_probe(path, probe)
            source_duration = _validate_probe(measured)
            ref = {
                "genre_number": genre["number"],
                "genre_slug": genre["slug"],
                "path": str(path),
                "bytes": source_bytes,
                "sha256": source_digest,
                "source_duration": source_duration,
                "probe": measured,
            }
            references.append(ref)
            genre_refs.append(ref)

        if not genre_refs:
            raise ValueError(f"genre {genre['slug']} has no references")
        total_duration = round(sum(float(ref["probe"].get("duration") or 0) for ref in genre_refs), 6)
        scene_change_evidence = [{
            "sha256": ref["sha256"],
            "source_duration": ref["source_duration"],
            "times": [float(time) for time in ref["probe"].get("scene_changes", [])],
        } for ref in genre_refs]
        scene_changes = [time for item in scene_change_evidence for time in item["times"]]
        scene_intervals = [
            later - earlier
            for earlier, later in zip(scene_changes, scene_changes[1:])  # noqa: RUF007
        ]
        style_samples = [
            sample
            for ref in genre_refs
            for sample in ref["probe"].get("style_samples", [])
        ]
        luma = [float(sample["luma"]) for sample in style_samples if "luma" in sample]
        saturation = [

View on GitHub (pinned to 8321021c54)