{"record":{"id":"4a51bc81de554c1f","repo":"calesthio/OpenMontage","slug":"diversify-requires-candidate-ids","errorCode":null,"errorMessage":"diversify requires 'candidate_ids'","messagePattern":"diversify requires 'candidate_ids'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/video/clip_search.py","lineNumber":333,"sourceCode":"        n=int(inputs.get(\"n\", 5)),\n        diversity=float(inputs.get(\"diversity\", 0.3)),\n        candidate_pool=int(inputs.get(\"candidate_pool\", 30)),\n        exclude_ids=inputs.get(\"exclude_ids\") or [],\n    )\n    return {\n        \"seed_clip_id\": seed,\n        \"results\": [\n            {\"score\": score, \"record\": asdict(rec)}\n            for rec, score in results\n        ],\n    }\n\n\ndef _op_diversify(corp, inputs: dict[str, Any]) -> dict[str, Any]:\n    \"\"\"Pick the most mutually-dissimilar subset of a candidate list.\"\"\"\n    candidate_ids = inputs.get(\"candidate_ids\") or []\n    if not candidate_ids:\n        raise ValueError(\"diversify requires 'candidate_ids'\")\n\n    kept = corp.diversify(\n        candidate_ids=list(candidate_ids),\n        n=int(inputs.get(\"n\", 5)),\n        diversity=float(inputs.get(\"diversity\", 0.5)),\n    )\n    return {\n        \"input_count\": len(candidate_ids),\n        \"kept_count\": len(kept),\n        \"kept_ids\": kept,\n    }\n\n\ndef _op_get(corp, inputs: dict[str, Any]) -> dict[str, Any]:\n    \"\"\"Look up one clip_id and return its full record.\"\"\"\n    clip_id = inputs.get(\"clip_id\")\n    if not clip_id:\n        raise ValueError(\"get requires 'clip_id'\")","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/clip_search.py#L315-L351","documentation":"Raised by _op_diversify when inputs['candidate_ids'] is missing, None, or an empty list. diversify picks a mutually-dissimilar subset from a candidate list you supply; with no candidates there is nothing to select.","triggerScenarios":"Calling operation='diversify' standalone with no list; passing candidates under 'ids' or 'clip_ids'; a preceding rank_for_slot step returning zero results so the mapped candidate list is empty.","commonSituations":"Pipeline wiring where the candidate list comes from an earlier retrieval that can legitimately return empty; agent forgetting to forward the results of the previous tool call.","solutions":["Forward the ids from your retrieval step: [r['record']['clip_id'] for r in rank_results['results']]","If the list can be empty, short-circuit before calling diversify (there is nothing to diversify)","Check the exact key name candidate_ids (not ids/clip_ids)"],"exampleFix":"# before\nresult = clip_search.run(inputs={'operation':'diversify','n':5})\n\n# after\nids = [r['record']['clip_id'] for r in ranked['results']]\nresult = clip_search.run(inputs={'operation':'diversify','candidate_ids':ids,'n':5})","handlingStrategy":"validation","validationCode":"candidates = [r['record']['clip_id'] for r in (ranked.get('results') or [])]\nif not candidates:\n    raise ValueError('no candidates to diversify — earlier retrieval returned nothing')\ninputs['candidate_ids'] = candidates","typeGuard":"def valid_candidates(inputs: dict) -> bool:\n    c = inputs.get('candidate_ids')\n    return isinstance(c, list) and len(c) > 0","tryCatchPattern":"try:\n    result = clip_search.run(inputs=inputs)\nexcept ValueError as e:\n    if 'candidate_ids' in str(e):\n        raise SystemExit('diversify needs a non-empty candidate list') from e\n    raise","preventionTips":["Forward ids from the retrieval step at the call site; never hand-type them","Short-circuit the diversify stage when retrieval returns zero results","Check the key is candidate_ids, not ids or clip_ids"],"tags":["clip-search","validation","retrieval"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}