{"record":{"id":"d2706866990a9bcc","repo":"ruvnet/RuView","slug":"size-must-be-1","errorCode":null,"errorMessage":"Size must be >= 1","messagePattern":"Size must be >= 1","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"archive/v1/src/api/dependencies.py","lineNumber":344,"sourceCode":"\n# Pagination dependencies\nclass PaginationParams:\n    \"\"\"Pagination parameters.\"\"\"\n    \n    def __init__(\n        self,\n        page: int = 1,\n        size: int = 20,\n        max_size: int = 100\n    ):\n        if page < 1:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail=\"Page must be >= 1\"\n            )\n        \n        if size < 1:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail=\"Size must be >= 1\"\n            )\n        \n        if size > max_size:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail=f\"Size must be <= {max_size}\"\n            )\n        \n        self.page = page\n        self.size = size\n        self.offset = (page - 1) * size\n        self.limit = size\n\n\ndef get_pagination_params(\n    page: int = 1,","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/api/dependencies.py#L326-L362","documentation":"Raised as HTTP 400 by PaginationParams at dependencies.py:344 when the `size` query parameter is less than 1. `size` is used both as the SQL-style LIMIT and as the offset multiplier, so zero or negative sizes are meaningless and rejected before the route runs. The default size is 20.","triggerScenarios":"Any endpoint using get_pagination_params called with ?size=0 or a negative size, e.g. GET /api/v1/detections?page=1&size=0.","commonSituations":"A 'fetch everything' attempt sends size=0 expecting it to mean unlimited; an empty UI input is parsed to 0 and sent; a caller sends -1 hoping for reversed paging.","solutions":["Send size >= 1 (default 20)","For 'fetch all', page through results with size=100 instead of size=0","Validate and clamp user input before building the query string"],"exampleFix":"# before\nsize = int(request.args.get('size', 0))\n\n# after\nsize = max(1, min(int(request.args.get('size', 20)), 100))","handlingStrategy":"validation","validationCode":"def safe_size(size, max_size=100):\n    value = int(size) if size is not None else 20\n    return max(1, value)  # pair with min(value, max_size) to also dodge the <=100 error","typeGuard":"def is_valid_size(size, max_size=100) -> bool:\n    return isinstance(size, int) and 1 <= size <= max_size","tryCatchPattern":"resp = await client.get('/api/v1/detections', params=params)\nif resp.status_code == 400 and 'Size must be >= 1' in resp.json().get('detail', ''):\n    params['size'] = 20\n    resp = await client.get('/api/v1/detections', params=params)\nresp.raise_for_status()","preventionTips":["Never send size=0 to mean 'unlimited' — this API has no unlimited mode","Coerce and clamp numeric inputs at the client boundary, not at the fetch call","For large datasets, page with size=100 instead of abusing size"],"tags":["python","fastapi","pagination","validation","http-400"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}