{"record":{"id":"86a55a0f0d422dbf","repo":"opendatalab/MinerU","slug":"local-max-and-server-max-must-both-be-positive-int","errorCode":null,"errorMessage":"local_max and server_max must both be positive integers","messagePattern":"local_max and server_max must both be positive integers","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mineru/cli/api_client.py","lineNumber":703,"sourceCode":"            i += 1\n            continue\n\n        remaining_args.append(arg)\n        i += 1\n\n    return tuple(remaining_args)\n\n\ndef normalize_base_url(url: str) -> str:\n    return url.rstrip(\"/\")\n\n\ndef resolve_effective_max_concurrent_requests(\n    local_max: int,\n    server_max: int,\n) -> int:\n    if local_max <= 0 or server_max <= 0:\n        raise ValueError(\n            \"local_max and server_max must both be positive integers\"\n        )\n    return min(local_max, server_max)\n\n\ndef response_detail(response: httpx.Response) -> str:\n    try:\n        payload = response.json()\n    except Exception:\n        text = response.text.strip()\n        return text or response.reason_phrase\n\n    if isinstance(payload, dict):\n        detail = payload.get(\"detail\")\n        if isinstance(detail, str):\n            return detail\n        error = payload.get(\"error\")\n        if isinstance(error, str):","sourceCodeStart":685,"sourceCodeEnd":721,"githubUrl":"https://github.com/opendatalab/MinerU/blob/4fe4bde114a23ee5dd637eae99b767f4669bf58c/mineru/cli/api_client.py#L685-L721","documentation":"resolve_effective_max_concurrent_requests() computes min(local_max, server_max) and requires both bounds to be strictly positive. Passing zero or a negative number (or None coerced to 0) for either limit raises immediately, since a non-positive concurrency cap is meaningless.","triggerScenarios":"Calling the function with local_max=0 or server_max=0 (e.g. a CLI flag --max-concurrent-requests 0, or a server-reported limit parsed as 0 because the field was missing in the JSON response).","commonSituations":"Users setting concurrency to 0 expecting 'unlimited'; server responses where the max-concurrency field is absent and int(payload.get('max_concurrent_requests', 0)) defaults to 0; config files with -1 as a 'disabled' sentinel.","solutions":["Pass a positive integer; use a large number (e.g. 10**6) if you want 'effectively unlimited'","If the value comes from a server response, default it to a sane positive value, not 0, when the field is missing","Validate CLI input before submission (see resolve_submit_concurrency which raises the sibling error)","Check that arithmetic on limits (e.g. max-1) never lands on 0"],"exampleFix":"# before\neffective = resolve_effective_max_concurrent_requests(local_max=0, server_max=8)\n\n# after\neffective = resolve_effective_max_concurrent_requests(local_max=8, server_max=8)","handlingStrategy":"validation","validationCode":"def safe_effective_max(local_max: int, server_max: int, default: int = 4) -> int:\n    local_max = local_max if isinstance(local_max, int) and local_max > 0 else default\n    server_max = server_max if isinstance(server_max, int) and server_max > 0 else default\n    return min(local_max, server_max)","typeGuard":"def is_positive_int(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and v > 0","tryCatchPattern":"try:\n    effective = resolve_effective_max_concurrent_requests(local_max, server_max)\nexcept ValueError:\n    effective = min(local_max or 4, server_max or 4) or 4  # last-resort sane default","preventionTips":["Never use 0 to mean 'unlimited' — use a large bound like 10**6","Default missing server fields to a positive value when parsing responses","Assert positivity of any concurrency knob right after CLI/config parsing"],"tags":["concurrency","validation","api-client"],"backgroundTag":null,"analyzedSha":"4fe4bde114a23ee5dd637eae99b767f4669bf58c","analyzedAt":"2026-08-14T21:29:18.456Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}