mattermost-community/focalboard · error

category doesn't belong to user

Error message

category doesn't belong to user

What it means

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.

Source

Thrown at server/model/error.go:21

import (
	"database/sql"
	"errors"
	"fmt"
	"net/http"
	"strings"

	mmModel "github.com/mattermost/mattermost/server/public/model"

	pluginapi "github.com/mattermost/mattermost/server/public/pluginapi"
)

var (
	ErrViewsLimitReached        = errors.New("views limit reached for board")
	ErrPatchUpdatesLimitedCards = errors.New("patch updates cards that are limited")

	ErrInsufficientLicense = errors.New("appropriate license required")

	ErrCategoryPermissionDenied = errors.New("category doesn't belong to user")
	ErrCategoryDeleted          = errors.New("category is deleted")

	ErrBoardMemberIsLastAdmin = errors.New("cannot leave a board with no admins")

	ErrRequestEntityTooLarge = errors.New("request entity too large")

	ErrInvalidBoardSearchField = errors.New("invalid board search field")
)

// ErrNotFound is an error type that can be returned by store APIs
// when a query unexpectedly fetches no records.
type ErrNotFound struct {
	entity string
}

// NewErrNotFound creates a new ErrNotFound instance.
func NewErrNotFound(entity string) *ErrNotFound {
	return &ErrNotFound{

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Confirm the authenticated user owns the category before updating/deleting
  2. Create the category as the same user that will modify it
  3. Check you are not mixing up categoryID with boardID or another ID

Example fix

// before
err := app.UpdateCategory(userID, otherUsersCategoryID, patch)
// after
cat, err := app.GetCategory(userID, categoryID)
if err != nil || cat.UserID != userID {
    return errors.New("category does not belong to user")
}
err = app.UpdateCategory(userID, categoryID, patch)
Defensive patterns

Strategy: type-guard

Validate before calling

cat, err := app.GetCategory(userID, categoryID)
if err != nil || cat.UserID != userID {
    // abort: not this user's category
}

Type guard

func isCategoryPermissionErr(err error) bool {
    return errors.Is(err, model.ErrCategoryPermissionDenied)
}

Try / catch

err := app.DeleteCategory(userID, categoryID)
if errors.Is(err, model.ErrCategoryPermissionDenied) {
    // show permission-denied message, do not retry
}

Prevention

When it happens

Trigger: 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.

Common situations: Admins trying to reorder another user's sidebar categories via API; clients caching category IDs across accounts; tests reusing fixtures from another user.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of mattermost-community/focalboard@a84bbb65e3 (2026-08-30). Data as JSON: /api/errors/f2f9f6b183397ecc. Report an issue: GitHub.