{"record":{"id":"b7b502185059354c","repo":"Significant-Gravitas/AutoGPT","slug":"transaction-count-limit-must-be-between-1-and-1000","errorCode":null,"errorMessage":"Transaction count limit must be between 1 and 1000","messagePattern":"Transaction count limit must be between 1 and 1000","errorType":"exception","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/v1.py","lineNumber":1578,"sourceCode":"    credit_model = await get_credit_model(user_id, ctx.org_id)\n    return {\"url\": await credit_model.create_billing_portal_session(user_id)}\n\n\n@v1_router.get(\n    path=\"/credits/transactions\",\n    tags=[\"credits\"],\n    summary=\"Get credit history\",\n    dependencies=[Security(requires_user)],\n)\nasync def get_credit_history(\n    user_id: Annotated[str, Security(get_user_id)],\n    ctx: Annotated[RequestContext, Security(get_request_context)],\n    transaction_time: datetime | None = None,\n    transaction_type: str | None = None,\n    transaction_count_limit: int = 100,\n) -> TransactionHistory:\n    if transaction_count_limit < 1 or transaction_count_limit > 1000:\n        raise ValueError(\"Transaction count limit must be between 1 and 1000\")\n\n    credit_model = await get_credit_model(user_id, ctx.org_id)\n    return await credit_model.get_transaction_history(\n        user_id=user_id,\n        transaction_time_ceiling=transaction_time,\n        transaction_count_limit=transaction_count_limit,\n        transaction_type=transaction_type,\n    )\n\n\n@v1_router.get(\n    path=\"/credits/refunds\",\n    tags=[\"credits\"],\n    summary=\"Get refund requests\",\n    dependencies=[Security(requires_user)],\n)\nasync def get_refund_requests(\n    user_id: Annotated[str, Security(get_user_id)],","sourceCodeStart":1560,"sourceCodeEnd":1596,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/v1.py#L1560-L1596","documentation":"A bare `raise ValueError(...)` inside the get_credit_history async route when transaction_count_limit is outside [1, 1000]. Unlike every other check in this file it is NOT an HTTPException, so FastAPI's generic exception handler converts it into an unlogged 500 Internal Server Error rather than a 422 — the client sees a server bug, not a validation message.","triggerScenarios":"GET /credits with transaction_count_limit=0, a negative value, or >1000 (e.g. a dashboard 'load all history' button passing 10000). The response is a 500 with a generic 'Internal Server Error' detail.","commonSituations":"Frontends paginating credit history and computing limits dynamically (total count > 1000); API consumers assuming uncapped limits; the 500 masking the real cause so devs hunt for server faults instead of their query param.","solutions":["Clamp the request to 1 <= transaction_count_limit <= 1000 (paginate with transaction_time cursor for more rows).","Fix the endpoint: replace the bare ValueError with FastAPI Query constraints — `transaction_count_limit: Annotated[int, Query(ge=1, le=1000)] = 100` — so clients get a proper 422.","At minimum change the raise to HTTPException(status_code=422, detail=...) to match the file's conventions."],"exampleFix":"# before\n    transaction_count_limit: int = 100,\n) -> TransactionHistory:\n    if transaction_count_limit < 1 or transaction_count_limit > 1000:\n        raise ValueError(\"Transaction count limit must be between 1 and 1000\")\n\n# after\n    transaction_count_limit: Annotated[int, Query(ge=1, le=1000)] = 100,\n) -> TransactionHistory:\n    ...","handlingStrategy":"validation","validationCode":"const limit = Math.min(Math.max(requestedLimit, 1), 1000);\nawait api.getCreditHistory({ transaction_count_limit: limit });","typeGuard":"const isValidLimit = (n: number) => Number.isInteger(n) && n >= 1 && n <= 1000;","tryCatchPattern":"catch (e) { if (e.response?.status === 500 && limitParamOutOfRange) { clampLimitAndRetry(); } else throw e; } // note: server currently returns 500, not 422","preventionTips":["Always clamp limit params to the documented [1,1000] window before sending.","For full history, paginate using transaction_time as a descending cursor instead of raising the limit.","Patch the endpoint to use Query(ge=1, le=1000) so violations return a proper 422."],"tags":["api","validation","pagination","bug","http-500","query-params"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}