mattermost-community/focalboard · error

moveBoardsToDefaultCategory: %w

Error message

moveBoardsToDefaultCategory: %w

What it means

moveBoardsToDefaultCategory returns this error when the team has no default category to receive boards whose source category is being deleted. It wraps the sentinel errNoDefaultCategoryFound so callers can detect it with errors.Is. It surfaces through DeleteCategory whenever board reassignment is required but no default category exists for the user/team.

Source

Thrown at server/app/category.go:178

			sourceCategoryBoards = &categoryBoards[i]
		}

		if categoryBoards[i].Name == defaultCategoryBoards {
			defaultCategoryID = categoryBoards[i].ID
		}

		// if both categories are found, no need to iterate furthur.
		if sourceCategoryBoards != nil && defaultCategoryID != "" {
			break
		}
	}

	if sourceCategoryBoards == nil {
		return errCategoryNotFound
	}

	if defaultCategoryID == "" {
		return fmt.Errorf("moveBoardsToDefaultCategory: %w", errNoDefaultCategoryFound)
	}

	boardIDs := make([]string, len(sourceCategoryBoards.BoardMetadata))
	for i := range sourceCategoryBoards.BoardMetadata {
		boardIDs[i] = sourceCategoryBoards.BoardMetadata[i].BoardID
	}

	if err := a.AddUpdateUserCategoryBoard(teamID, userID, defaultCategoryID, boardIDs); err != nil {
		return fmt.Errorf("moveBoardsToDefaultCategory: %w", err)
	}

	return nil
}

func (a *App) ReorderCategories(userID, teamID string, newCategoryOrder []string) ([]string, error) {
	if err := a.verifyNewCategoriesMatchExisting(userID, teamID, newCategoryOrder); err != nil {
		return nil, err
	}

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Ensure each team has a default category (create one if missing) before allowing category deletion
  2. Check for the sentinel with errors.Is(err, errNoDefaultCategoryFound) and surface a clear message to create a default category first
  3. Migrate legacy teams to have a default category
  4. Delete or move the boards manually before deleting the category

Example fix

// before
err := app.DeleteCategory(userID, teamID, categoryID)
// after
err := app.DeleteCategory(userID, teamID, categoryID)
if errors.Is(err, errNoDefaultCategoryFound) {
	// create/recreate a default category for the team first
}
Defensive patterns

Strategy: try-catch

Validate before calling

cats, err := app.GetCategoriesForTeam(teamID, userID)
if err != nil {
	return err
}
hasDefault := false
for _, c := range cats {
	if c.ID == defaultCategoryID || (c.Type == model.CategoryTypeDefault) {
		hasDefault = true
	}
}
if !hasDefault {
	// create a default category before deleting a non-empty one
}

Type guard

func isNoDefaultCategory(err error) bool {
	return errors.Is(err, errNoDefaultCategoryFound)
}

Try / catch

err := app.DeleteCategory(userID, teamID, categoryID)
if isNoDefaultCategory(err) {
	// prompt user to create a default category first
}

Prevention

When it happens

Trigger: Calling DeleteCategory (directly or via the REST DELETE category endpoint) on a category that contains boards, when the user's team has no default category — i.e., defaultCategoryID resolves to empty string — so the boards cannot be moved anywhere.

Common situations: Teams provisioned before default categories were introduced, or where the default category was deleted; test/seed data lacking a default category; API consumers deleting non-empty categories on freshly created teams.

Related errors


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