mattermost-community/focalboard · warning

category is deleted

Error message

category is deleted

What it means

ErrCategoryDeleted indicates the category has been marked as deleted. Deleted categories are soft-deleted but still present in storage, so lookups succeed while mutations are rejected. IsErrNotFound maps it to HTTP 404 so clients treat it as a missing resource.

Source

Thrown at server/model/error.go:22

	"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{
		entity: entity,

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Refresh the category list and retry with a valid category ID
  2. Treat the category as gone and recreate it if needed
  3. Check DeleteAt before issuing updates

Example fix

// before
err := app.UpdateCategory(userID, categoryID, patch)
// after
err := app.UpdateCategory(userID, categoryID, patch)
if errors.Is(err, model.ErrCategoryDeleted) {
    return app.CreateCategory(userID, patch.Name)
}
Defensive patterns

Strategy: type-guard

Validate before calling

cat, err := app.GetCategory(userID, categoryID)
if err == nil && cat.DeleteAt != 0 {
    // treat as deleted; refresh UI state
}

Type guard

func isCategoryDeletedErr(err error) bool {
    return errors.Is(err, model.ErrCategoryDeleted)
}

Try / catch

err := app.UpdateCategory(userID, categoryID, patch)
if errors.Is(err, model.ErrCategoryDeleted) {
    return app.CreateCategory(userID, patch.Name) // recreate instead
}

Prevention

When it happens

Trigger: UpdateCategory (or reorder operations) targeting a category whose DeleteAt is already set; two concurrent requests where one deletes the category the other updates; re-deleting an already deleted category.

Common situations: Race between deleting a category in one tab and editing it in another; retry logic replaying updates after a delete; stale client caches referencing deleted categories.

Related errors


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