{"record":{"id":"96c2cbd2a7b7aa6e","repo":"Zie619/n8n-workflows","slug":"rating-must-be-between-1-and-5","errorCode":null,"errorMessage":"Rating must be between 1 and 5","messagePattern":"Rating must be between 1 and 5","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"src/community_features.py","lineNumber":133,"sourceCode":"                workflow_id TEXT NOT NULL,\n                user_id TEXT NOT NULL,\n                parent_id INTEGER, -- For threaded comments\n                comment TEXT NOT NULL,\n                helpful_votes INTEGER DEFAULT 0,\n                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n            )\n        \"\"\")\n\n        conn.commit()\n        conn.close()\n\n    def add_rating(\n        self, workflow_id: str, user_id: str, rating: int, review: str = None\n    ) -> bool:\n        \"\"\"Add or update a workflow rating and review\"\"\"\n        if not (1 <= rating <= 5):\n            raise ValueError(\"Rating must be between 1 and 5\")\n\n        conn = sqlite3.connect(self.db_path)\n        cursor = conn.cursor()\n\n        try:\n            # Insert or update rating\n            cursor.execute(\n                \"\"\"\n                INSERT OR REPLACE INTO workflow_ratings \n                (workflow_id, user_id, rating, review, updated_at)\n                VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)\n            \"\"\",\n                (workflow_id, user_id, rating, review),\n            )\n\n            # Update workflow statistics\n            self._update_workflow_stats(workflow_id)\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/src/community_features.py#L115-L151","documentation":"A ValueError raised by CommunityFeatures.add_rating when the rating argument falls outside the inclusive range 1..5. It is explicit input validation before any DB write, so no SQLite state is touched when it fires. Callers that do not catch it will see it propagate up as an unhandled exception (or a 500 if raised inside an HTTP handler).","triggerScenarios":"Calling add_rating(workflow_id, user_id, rating=0), rating=6, rating=-1, or a non-integer value that Python comparison rejects; also rating passed as a string like '5' when type annotation is not enforced at runtime.","commonSituations":"Frontend star widget sending 0 for 'unrated'; off-by-one loop indexing producing 6; API endpoint forwarding unvalidated user input straight into add_rating; JSON body delivering rating as a string.","solutions":["Clamp or reject the value on the client before calling: only send integers 1 through 5.","If exposing via HTTP, validate with a Pydantic model field rating: int = Field(ge=1, le=5) so FastAPI returns 422 instead of a 500.","Catch the ValueError at the API boundary and map it to a 400 Bad Request with the message.","Audit star-widget code for 0-based indices (map index+1 before sending)."],"exampleFix":"# before\ncommunity.add_rating(wf_id, user_id, rating=stars)  # stars can be 0\n\n# after\nfrom pydantic import BaseModel, Field\n\nclass RatingIn(BaseModel):\n    rating: int = Field(ge=1, le=5)\n\nrating_in = RatingIn.model_validate({\"rating\": stars})\ncommunity.add_rating(wf_id, user_id, rating=rating_in.rating)","handlingStrategy":"validation","validationCode":"def is_valid_rating(rating) -> bool:\n    return isinstance(rating, int) and not isinstance(rating, bool) and 1 <= rating <= 5","typeGuard":"def is_valid_rating(rating) -> TypeGuard[bool] is not needed; use:\n\ndef is_valid_rating(value: object) -> bool:\n    \"\"\"True when value is an int in [1, 5] (bools excluded).\"\"\"\n    if isinstance(value, bool):\n        return False\n    return isinstance(value, int) and 1 <= value <= 5","tryCatchPattern":"try:\n    community.add_rating(wf_id, user_id, rating=stars)\nexcept ValueError as e:\n    if \"Rating must be between 1 and 5\" in str(e):\n        raise HTTPException(status_code=400, detail=str(e)) from e\n    raise","preventionTips":["Validate at the API boundary with Pydantic Field(ge=1, le=5) so bad input 422s instead of 500ing.","Guard star widgets: disable submit until a star is chosen (no 0-star submits).","Map this ValueError to 400 in HTTP layers; never let it surface as 500."],"tags":["validation","valueerror","ratings","input-validation","range-check"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}