{"record":{"id":"4e45077dfdb4c983","repo":"affaan-m/ECC","slug":"frame-count-must-be-an-exact-integer-in-range","errorCode":null,"errorMessage":"frame/count must be an exact integer in range","messagePattern":"frame/count must be an exact integer in range","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/integration.py","lineNumber":55,"sourceCode":"\n\ndef _object(value: Any, required: set[str], optional: set[str] | None = None) -> dict:\n    if not isinstance(value, dict) or not required <= value.keys():\n        raise ValueError(\"missing required bundle fields\")\n    if value.keys() - required - (optional or set()):\n        raise ValueError(\"unknown bundle fields\")\n    return value\n\n\ndef _text(value: Any) -> str:\n    if not isinstance(value, str) or not value.strip():\n        raise ValueError(\"nonempty text required\")\n    return value\n\n\ndef _integer(value: Any, minimum: int = 0) -> int:\n    if type(value) is not int or value < minimum:\n        raise ValueError(\"frame/count must be an exact integer in range\")\n    return value\n\n\ndef _rate(value: Any) -> tuple[int, int]:\n    _object(value, {\"numerator\", \"denominator\"})\n    n, d = (_integer(value[k], 1) for k in (\"numerator\", \"denominator\"))\n    if math.gcd(n, d) != 1:\n        raise ValueError(\"fps must be a reduced positive rational\")\n    return n, d\n\n\ndef _range(value: Any, bounds: list[int] | None = None) -> list[int]:\n    if not isinstance(value, list) or len(value) != 2:\n        raise ValueError(\"range must contain two frame integers\")\n    start, end = (_integer(v) for v in value)\n    if start >= end or (bounds is not None and (start < bounds[0] or end > bounds[1])):\n        raise ValueError(\"frame range is empty or outside its bounds\")\n    return value","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/integration.py#L37-L73","documentation":"_integer requires an exact int (bool excluded via type() check) greater than or equal to the minimum (default 0); anything else raises ValueError('frame/count must be an exact integer in range'). Frame indices and counts in the bundle must be exact whole numbers.","triggerScenarios":"Passing a float like 24.0, a bool, a string '24', or a negative frame number to any frame/count field (range endpoints, durations, rates' numerator/denominator with minimum 1).","commonSituations":"JSON parsers or APIs that produce floats for whole numbers, numpy integer types (np.int64) that fail the exact type() check, and negative values from off-by-one frame math.","solutions":["Coerce numeric values with int(v) and verify v == int(v) before building the bundle","Convert numpy scalars with .item()/int() so they become Python ints","Check for negative values in range/duration computations and clamp or fix the source math"],"exampleFix":"// before\nsnapshot = {\"duration_frames\": 240.0, ...}\n// after\nsnapshot = {\"duration_frames\": int(240.0), ...}","handlingStrategy":"type-guard","validationCode":"def as_frame(v):\n    if isinstance(v, bool) or not isinstance(v, int) or v < 0:\n        raise TypeError(f\"not a frame int: {v!r}\")\n    return v","typeGuard":"def is_frame_int(v) -> bool:\n    return type(v) is int and v >= 0","tryCatchPattern":"try:\n    bundle = build_application_bundle(data)\nexcept ValueError as e:\n    if \"exact integer\" in str(e):\n        print(\"frame/count field is not an exact int; coerce floats/numpy types\")\n    else:\n        raise","preventionTips":["Coerce with int(v) whenever frames come from float math or external APIs","Convert numpy integers with .item() before inserting into bundles","Never pass bools as counts; bools pass isinstance(int) but fail the exact-type check"],"tags":["type-mismatch","frames","validation"],"backgroundTag":"type-mismatch","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}