{"record":{"id":"f2f9f6b183397ecc","repo":"mattermost-community/focalboard","slug":"category-doesn-t-belong-to-user","errorCode":null,"errorMessage":"category doesn't belong to user","messagePattern":"category doesn't belong to user","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/model/error.go","lineNumber":21,"sourceCode":"import (\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\tmmModel \"github.com/mattermost/mattermost/server/public/model\"\n\n\tpluginapi \"github.com/mattermost/mattermost/server/public/pluginapi\"\n)\n\nvar (\n\tErrViewsLimitReached        = errors.New(\"views limit reached for board\")\n\tErrPatchUpdatesLimitedCards = errors.New(\"patch updates cards that are limited\")\n\n\tErrInsufficientLicense = errors.New(\"appropriate license required\")\n\n\tErrCategoryPermissionDenied = errors.New(\"category doesn't belong to user\")\n\tErrCategoryDeleted          = errors.New(\"category is deleted\")\n\n\tErrBoardMemberIsLastAdmin = errors.New(\"cannot leave a board with no admins\")\n\n\tErrRequestEntityTooLarge = errors.New(\"request entity too large\")\n\n\tErrInvalidBoardSearchField = errors.New(\"invalid board search field\")\n)\n\n// ErrNotFound is an error type that can be returned by store APIs\n// when a query unexpectedly fetches no records.\ntype ErrNotFound struct {\n\tentity string\n}\n\n// NewErrNotFound creates a new ErrNotFound instance.\nfunc NewErrNotFound(entity string) *ErrNotFound {\n\treturn &ErrNotFound{","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/model/error.go#L3-L39","documentation":"ErrCategoryPermissionDenied indicates the category being modified does not belong to the requesting user. Categories (sidebar groupings of boards) are per-user, so update/delete operations verify ownership and return this sentinel error on mismatch. IsErrForbidden maps it to HTTP 403.","triggerScenarios":"UpdateCategory or DeleteCategory with a categoryID owned by a different user; passing another user's category ID due to stale client state or ID confusion.","commonSituations":"Admins trying to reorder another user's sidebar categories via API; clients caching category IDs across accounts; tests reusing fixtures from another user.","solutions":["Confirm the authenticated user owns the category before updating/deleting","Create the category as the same user that will modify it","Check you are not mixing up categoryID with boardID or another ID"],"exampleFix":"// before\nerr := app.UpdateCategory(userID, otherUsersCategoryID, patch)\n// after\ncat, err := app.GetCategory(userID, categoryID)\nif err != nil || cat.UserID != userID {\n    return errors.New(\"category does not belong to user\")\n}\nerr = app.UpdateCategory(userID, categoryID, patch)","handlingStrategy":"type-guard","validationCode":"cat, err := app.GetCategory(userID, categoryID)\nif err != nil || cat.UserID != userID {\n    // abort: not this user's category\n}","typeGuard":"func isCategoryPermissionErr(err error) bool {\n    return errors.Is(err, model.ErrCategoryPermissionDenied)\n}","tryCatchPattern":"err := app.DeleteCategory(userID, categoryID)\nif errors.Is(err, model.ErrCategoryPermissionDenied) {\n    // show permission-denied message, do not retry\n}","preventionTips":["Always verify category ownership before mutation","Never reuse category IDs across user sessions","Map this error to HTTP 403 in API handlers"],"tags":["go","permissions","forbidden","categories"],"backgroundTag":"permission-denied","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}