{"record":{"id":"adbf7b2e1adbc83c","repo":"cocoindex-io/cocoindex","slug":"report-to-stdout-interval-must-be-a-positive-durat","errorCode":null,"errorMessage":"report_to_stdout interval must be a positive duration","messagePattern":"report_to_stdout interval must be a positive duration","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/update_stats.py","lineNumber":26,"sourceCode":"R = TypeVar(\"R\")\n\n_TERMINATED_VERSION = 2**64 - 1  # u64::MAX\n\n\ndef _resolve_report_to_stdout(\n    report_to_stdout: bool | timedelta,\n) -> tuple[bool, float | None]:\n    \"\"\"Normalize a ``bool | timedelta`` progress flag into\n    ``(enabled, refresh_interval_secs)`` for the core boundary.\n\n    - ``False`` → ``(False, None)`` (no report)\n    - ``True`` → ``(True, None)`` (report at the default interval)\n    - ``timedelta`` → ``(True, secs)`` (report at that interval; must be positive)\n    \"\"\"\n    if isinstance(report_to_stdout, timedelta):\n        secs = report_to_stdout.total_seconds()\n        if secs <= 0:\n            raise ValueError(\"report_to_stdout interval must be a positive duration\")\n        return True, secs\n    return bool(report_to_stdout), None\n\n\nclass _CoreStatsHandle(Protocol):\n    \"\"\"Structural interface shared by the core update / drop / stats-group\n    handles — everything `_StatsView` needs to read progress.\"\"\"\n\n    def stats_snapshot(self) -> tuple[int, bool, dict[str, dict[str, int]]]: ...\n    def changed(self) -> Coroutine[Any, Any, int]: ...\n\n\nH = TypeVar(\"H\", bound=_CoreStatsHandle)\n\n\ndef _decode_update_stats(raw: dict[str, dict[str, int]]) -> UpdateStats:\n    \"\"\"Decode the raw `{processor: {field: value}}` snapshot from core.\"\"\"\n    return UpdateStats(","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/update_stats.py#L8-L44","documentation":"When report_to_stdout is given as a timedelta to update_blocking/drop_blocking/stats_group, the interval must be strictly positive; zero or negative durations cannot drive progress reporting. _resolve_report_to_stdout validates this before starting the update.","triggerScenarios":"Calling app.update_blocking(report_to_stdout=timedelta(0)), a negative timedelta, or a timedelta(seconds=0) derived from computation, to any of update_blocking, drop_blocking, or stats_group.","commonSituations":"Computing an interval dynamically (e.g. total_time/2) that evaluates to 0 for fast runs; passing timedelta() default which is zero; sign errors when constructing the interval.","solutions":["Pass a positive timedelta, e.g. timedelta(seconds=1) or timedelta(milliseconds=500)","Guard computed intervals: if secs <= 0, fall back to the default (report_to_stdout=True)","Use report_to_stdout=True for the default interval instead of an explicit duration"],"exampleFix":"// before\napp.update_blocking(report_to_stdout=timedelta(0))\n// after\ninterval = max(timedelta(seconds=1), computed_interval)\napp.update_blocking(report_to_stdout=interval)","handlingStrategy":"validation","validationCode":"if isinstance(report_to_stdout, timedelta) and report_to_stdout.total_seconds() <= 0:\n    report_to_stdout = True  # fall back to default interval","typeGuard":"def is_valid_interval(d: timedelta) -> bool:\n    return d.total_seconds() > 0","tryCatchPattern":"try:\n    app.update_blocking(report_to_stdout=interval)\nexcept ValueError as e:\n    app.update_blocking(report_to_stdout=True)  # default interval","preventionTips":["Never pass timedelta(0) — the default constructor is zero","Clamp computed intervals to a positive minimum (e.g. 1s)","Prefer report_to_stdout=True unless a custom cadence is required"],"tags":["validation","duration","arguments"],"backgroundTag":"invalid-duration-format","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}