mattermost-community/focalboard · error

failed to insert board %s history: %w

Error message

failed to insert board %s history: %w

What it means

After successfully writing the boards row (insert or update), insertBoard writes an audit record into boards_history; if that INSERT Exec fails, this wrapped error is returned — the board itself may be persisted but the call reports failure. The board ID and driver error are logged server-side before wrapping.

Source

Thrown at server/services/store/sqlstore/board.go:398

			return nil, fmt.Errorf("insertBoard error occurred while updating existing board %s: %w", board.ID, err)
		}
	} else {
		board.CreatedBy = userID
		board.CreateAt = now
		insertQueryValues["created_by"] = board.CreatedBy
		insertQueryValues["create_at"] = board.CreateAt

		query := insertQuery.SetMap(insertQueryValues).Into(s.tablePrefix + "boards")
		if _, err := query.Exec(); err != nil {
			return nil, fmt.Errorf("insertBoard error occurred while inserting board %s: %w", board.ID, err)
		}
	}

	// writing board history
	query := insertQuery.SetMap(insertQueryValues).Into(s.tablePrefix + "boards_history")
	if _, err := query.Exec(); err != nil {
		s.logger.Error("failed to insert board history", mlog.String("board_id", board.ID), mlog.Err(err))
		return nil, fmt.Errorf("failed to insert board %s history: %w", board.ID, err)
	}

	return board, nil
}

func (s *SQLStore) patchBoard(db sq.BaseRunner, boardID string, boardPatch *model.BoardPatch, userID string) (*model.Board, error) {
	existingBoard, err := s.getBoard(db, boardID)
	if err != nil {
		return nil, err
	}

	board := boardPatch.Patch(existingBoard)
	return s.insertBoard(db, board, userID)
}

func (s *SQLStore) deleteBoard(db sq.BaseRunner, boardID, userID string) error {
	return s.deleteBoardAndChildren(db, boardID, userID, false)
}

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Read the wrapped err and server log 'failed to insert board history' for the driver detail
  2. Run migrations to ensure the boards_history table exists and matches schema expectations
  3. Check DB health: disk space, connection stability, read/write permissions on boards_history
  4. Retry the operation — the main board row insert is the same operation, so a clean retry (with a new ID if duplicate-key arises) usually succeeds

Example fix

// before
// boards_history table missing after partial migration
// after: apply all migrations
migrate_db.sh  # creates boards_history
restart server
Defensive patterns

Strategy: retry

Try / catch

board, err := store.InsertBoard(board, userID)
if err != nil && strings.Contains(err.Error(), "failed to insert board") {
    // board may exist; check before retrying to avoid duplicate
    if existing, gerr := store.GetBoard(board.ID); gerr != nil || existing == nil {
        board, err = store.InsertBoard(board, userID)
    }
}

Prevention

When it happens

Trigger: Any successful board write followed by a failing boards_history insert — typically because the boards_history table is missing (incomplete migration), corrupted, or the DB connection dropped between the two statements.

Common situations: Upgrading from versions without history tables without running full migrations; manually pruning boards_history and dropping required constraints/columns; disk-full or read-only replicas; transient connection loss mid-transaction.

Related errors


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