{"record":{"id":"bfdb0778ec2435af","repo":"mattermost-community/focalboard","slug":"cannot-save-member-s-while-inserting-board-s-w","errorCode":null,"errorMessage":"cannot save member %s while inserting board %s: %w","messagePattern":"cannot save member (.+?) while inserting board (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/sqlstore/board.go","lineNumber":496,"sourceCode":"\treturn s.deleteBlockChildren(db, boardID, \"\", userID)\n}\n\nfunc (s *SQLStore) insertBoardWithAdmin(db sq.BaseRunner, board *model.Board, userID string) (*model.Board, *model.BoardMember, error) {\n\tnewBoard, err := s.insertBoard(db, board, userID)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tbm := &model.BoardMember{\n\t\tBoardID:      newBoard.ID,\n\t\tUserID:       newBoard.CreatedBy,\n\t\tSchemeAdmin:  true,\n\t\tSchemeEditor: true,\n\t}\n\n\tnbm, err := s.saveMember(db, bm)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"cannot save member %s while inserting board %s: %w\", bm.UserID, bm.BoardID, err)\n\t}\n\n\treturn newBoard, nbm, nil\n}\n\nfunc (s *SQLStore) saveMember(db sq.BaseRunner, bm *model.BoardMember) (*model.BoardMember, error) {\n\tqueryValues := map[string]interface{}{\n\t\t\"board_id\":         bm.BoardID,\n\t\t\"user_id\":          bm.UserID,\n\t\t\"roles\":            \"\",\n\t\t\"scheme_admin\":     bm.SchemeAdmin,\n\t\t\"scheme_editor\":    bm.SchemeEditor,\n\t\t\"scheme_commenter\": bm.SchemeCommenter,\n\t\t\"scheme_viewer\":    bm.SchemeViewer,\n\t}\n\n\toldMember, err := s.getMemberForBoard(db, bm.BoardID, bm.UserID)\n\tif err != nil && !model.IsErrNotFound(err) {","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/sqlstore/board.go#L478-L514","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnbm, err := s.saveMember(db, bm)\nif err != nil {\n\treturn nil, nil, fmt.Errorf(\"cannot save member %s while inserting board %s: %w\", bm.UserID, bm.BoardID, err)\n}\n// after\nnbm, err := s.saveMember(db, bm)\nif err != nil {\n\tif errors.Is(err, sql.ErrNoRows) {\n\t\treturn nil, nil, fmt.Errorf(\"user %s not found while inserting board %s\", bm.UserID, bm.BoardID)\n\t}\n\treturn nil, nil, fmt.Errorf(\"cannot save member %s while inserting board %s: %w\", bm.UserID, bm.BoardID, err)\n}","handlingStrategy":"try-catch","validationCode":"const ok, err := db.Ping(); if err != nil || !ok { /* don't attempt board creation */ }","typeGuard":"func isSaveMemberError(err error) (*model.BoardMember, bool) {\n\tvar target error\n\tif errors.As(err, &target) && strings.Contains(target.Error(), \"cannot save member\") {\n\t\treturn nil, true\n\t}\n\treturn nil, false\n}","tryCatchPattern":"nbm, err := store.InsertBoardWithAdmin(board, bm)\nif err != nil {\n\tif strings.Contains(err.Error(), \"cannot save member\") {\n\t\t// inspect errors.Unwrap(err) for duplicate key / FK violation, clean up board_members, then retry\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["database","sql","transaction","focalboard"],"backgroundTag":"sql-constraint-violation","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}