mattermost-community/focalboard · error
cannot save member %s while inserting board %s: %w
Error message
cannot save member %s while inserting board %s: %w
What it means
Wraparound error in SQLStore.InsertBoardWithAdmin (server/services/store/sqlstore/board.go:496). After inserting the board row within the same transaction, the store saves the admin board-member row via saveMember(db, bm). If that insert fails, the whole board creation is aborted and the underlying DB error is wrapped with the user ID and board ID so the caller knows which member/board pair failed.
Source
Thrown at server/services/store/sqlstore/board.go:496
return s.deleteBlockChildren(db, boardID, "", userID)
}
func (s *SQLStore) insertBoardWithAdmin(db sq.BaseRunner, board *model.Board, userID string) (*model.Board, *model.BoardMember, error) {
newBoard, err := s.insertBoard(db, board, userID)
if err != nil {
return nil, nil, err
}
bm := &model.BoardMember{
BoardID: newBoard.ID,
UserID: newBoard.CreatedBy,
SchemeAdmin: true,
SchemeEditor: true,
}
nbm, err := s.saveMember(db, bm)
if err != nil {
return nil, nil, fmt.Errorf("cannot save member %s while inserting board %s: %w", bm.UserID, bm.BoardID, err)
}
return newBoard, nbm, nil
}
func (s *SQLStore) saveMember(db sq.BaseRunner, bm *model.BoardMember) (*model.BoardMember, error) {
queryValues := map[string]interface{}{
"board_id": bm.BoardID,
"user_id": bm.UserID,
"roles": "",
"scheme_admin": bm.SchemeAdmin,
"scheme_editor": bm.SchemeEditor,
"scheme_commenter": bm.SchemeCommenter,
"scheme_viewer": bm.SchemeViewer,
}
oldMember, err := s.getMemberForBoard(db, bm.BoardID, bm.UserID)
if err != nil && !model.IsErrNotFound(err) {View on GitHub (pinned to a84bbb65e3)
Solutions
- Inspect the wrapped underlying error (%w cause) in logs to identify the exact DB failure (duplicate key, FK violation, connection error).
- Query the board_members table for existing rows with the offending board_id/user_id and delete stale duplicates before retrying.
- Verify the user and board rows exist and the DB schema matches the expected version (run migrations).
- Retry the board creation; if persistent, check DB connectivity, pool limits, and lock contention.
- Upgrade/repair the plugin database schema if the error is a missing-column or constraint error after a version change.
Example fix
// before
nbm, err := s.saveMember(db, bm)
if err != nil {
return nil, nil, fmt.Errorf("cannot save member %s while inserting board %s: %w", bm.UserID, bm.BoardID, err)
}
// after
nbm, err := s.saveMember(db, bm)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil, fmt.Errorf("user %s not found while inserting board %s", bm.UserID, bm.BoardID)
}
return nil, nil, fmt.Errorf("cannot save member %s while inserting board %s: %w", bm.UserID, bm.BoardID, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
const ok, err := db.Ping(); if err != nil || !ok { /* don't attempt board creation */ } Type guard
func isSaveMemberError(err error) (*model.BoardMember, bool) {
var target error
if errors.As(err, &target) && strings.Contains(target.Error(), "cannot save member") {
return nil, true
}
return nil, false
} Try / catch
nbm, err := store.InsertBoardWithAdmin(board, bm)
if err != nil {
if strings.Contains(err.Error(), "cannot save member") {
// inspect errors.Unwrap(err) for duplicate key / FK violation, clean up board_members, then retry
}
return err
} Prevention
- Ensure unique (board_id, user_id) before inserting a member row
- Keep app and DB schema versions in sync (run all migrations)
- Monitor DB connectivity and pool saturation before write-heavy operations
- Back up and validate referential integrity after restores/imports
When it happens
Trigger: Calling InsertBoardWithAdmin (directly or via board creation API) when the board_members insert fails: e.g. duplicate (board_id, user_id) primary key on the board_members table, foreign-key violation because the user or board row is not visible to the transaction, schema mismatch after a partial migration, or DB connectivity/constraint failure during saveMember.
Common situations: Duplicated board-member rows left by an earlier failed import or migration; creating boards for users that were deleted concurrently; running an old schema against newer app code (missing columns/constraints on board_members); database outages or connection pool exhaustion mid-request.
Related errors
- store addUpdateCategoryBoard: failed to upsert user-board-ca
- cannot get blocks with same ID: %w
- cannot replace blockID %s: %w
- cannot mark migration as completed: %w
- cannot get migration state: %w
AI-assisted analysis of mattermost-community/focalboard@a84bbb65e3 (2026-08-30).
Data as JSON: /api/errors/bfdb0778ec2435af.
Report an issue: GitHub.