{"record":{"id":"d4a80cb823f59395","repo":"mattermost-community/focalboard","slug":"category-is-deleted","errorCode":null,"errorMessage":"category is deleted","messagePattern":"category is deleted","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/model/error.go","lineNumber":22,"sourceCode":"\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{\n\t\tentity: entity,","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/model/error.go#L4-L40","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Refresh the category list and retry with a valid category ID","Treat the category as gone and recreate it if needed","Check DeleteAt before issuing updates"],"exampleFix":"// before\nerr := app.UpdateCategory(userID, categoryID, patch)\n// after\nerr := app.UpdateCategory(userID, categoryID, patch)\nif errors.Is(err, model.ErrCategoryDeleted) {\n    return app.CreateCategory(userID, patch.Name)\n}","handlingStrategy":"type-guard","validationCode":"cat, err := app.GetCategory(userID, categoryID)\nif err == nil && cat.DeleteAt != 0 {\n    // treat as deleted; refresh UI state\n}","typeGuard":"func isCategoryDeletedErr(err error) bool {\n    return errors.Is(err, model.ErrCategoryDeleted)\n}","tryCatchPattern":"err := app.UpdateCategory(userID, categoryID, patch)\nif errors.Is(err, model.ErrCategoryDeleted) {\n    return app.CreateCategory(userID, patch.Name) // recreate instead\n}","preventionTips":["Refresh sidebar state after deletes to avoid stale references","Check DeleteAt before updates","Map this error to HTTP 404 in handlers"],"tags":["go","not-found","soft-delete","categories"],"backgroundTag":"resource-already-deleted","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}