{"record":{"id":"4a950b566c430771","repo":"siyuan-note/siyuan","slug":"rating-must-be-an-integer-from-0-to-5","errorCode":null,"errorMessage":"rating must be an integer from 0 to 5","messagePattern":"rating must be an integer from 0 to 5","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/bazaar_rating.go","lineNumber":138,"sourceCode":"\t\t\"token\":       token,\n\t\t\"packageName\": packageName,\n\t}, &data)\n\tif nil != err {\n\t\treturn nil, false, 0, err\n\t}\n\tif 0 > data.Rating || 5 < data.Rating {\n\t\treturn nil, false, 0, errors.New(\"invalid user rating returned by cloud server\")\n\t}\n\n\trating, ratingAvailable = bazaar.GetBazaarPackageRating(ctx, packageName)\n\treturn rating, ratingAvailable, data.Rating, nil\n}\n\n// SetBazaarPackageRating 设置或取消已安装官方包的当前用户评分。\nfunc SetBazaarPackageRating(ctx context.Context, pkgType, packageName string, userRating int) (rating *bazaar.PackageRating,\n\tratingAvailable bool, retUserRating int, err error) {\n\tif 0 > userRating || 5 < userRating {\n\t\treturn nil, false, 0, errors.New(\"rating must be an integer from 0 to 5\")\n\t}\n\tbazaarRatingSetMu.Lock()\n\tdefer bazaarRatingSetMu.Unlock()\n\n\ttoken, err := bazaarRatingValidatePackage(ctx, pkgType, packageName)\n\tif nil != err {\n\t\treturn nil, false, 0, err\n\t}\n\n\tregion := util.CurrentCloudRegion\n\tdata := bazaarPackageSetRatingData{}\n\terr = requestBazaarPackageRating(ctx, \"/apis/siyuan/bazaar/setBazaarPackageRating\", map[string]any{\n\t\t\"token\":       token,\n\t\t\"packageName\": packageName,\n\t\t\"rating\":      userRating,\n\t}, &data)\n\tif nil != err {\n\t\treturn nil, false, 0, err","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/bazaar_rating.go#L120-L156","documentation":"Error returned by model.SetBazaarPackageRating (kernel/model/bazaar_rating.go:138) when the caller-supplied userRating is outside 0..5. This is pure local input validation executed before taking the bazaarRatingSetMu lock and before any network call: 0 means 'clear my rating', 1..5 are star values, and anything else (negative, >5, or a value coerced from non-integer input) is rejected immediately.","triggerScenarios":"Calling /api/bazaar/setBazaarPackageRating with rating=6 from a UI star widget bug, rating=-1 to mean 'remove', or forwarding an unvalidated integer from a request body.","commonSituations":"Frontends mapping a 0-10 or 0-100 scale onto stars without dividing; 'clear rating' implemented as -1 instead of 0; default zero-value ints accidentally sent as a real 1-star rating when the user made no choice.","solutions":["Clamp/validate the value to 0..5 before the call (0 clears the rating)","Map your UI's scale to 1..5 stars explicitly and only send a request on explicit user action","Reject form submissions server-side in your client code with the same range check"],"exampleFix":"// before\nerr := setRating(ctx, pkgType, name, rawScore) // rawScore is 0..10 from the UI\n\n// after\nstars := (rawScore + 5) / 10 // map 0..10 to 0..5, or better: derive directly from star count\nif stars < 0 || stars > 5 {\n    return fmt.Errorf(\"rating must be 0..5, got %d\", stars)\n}\nerr := setRating(ctx, pkgType, name, stars)","handlingStrategy":"validation","validationCode":"if userRating < 0 || userRating > 5 {\n    return fmt.Errorf(\"rating must be 0..5, got %d\", userRating)\n}","typeGuard":"func isValidRating(r int) bool { return r >= 0 && r <= 5 }","tryCatchPattern":null,"preventionTips":["Map UI star widgets directly to 0..5; never forward raw scores from other scales","Use 0 explicitly for 'clear my rating' and document it in the client"],"tags":["marketplace","ratings","input-validation","range-check"],"backgroundTag":"input-validation-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}