mattermost-community/focalboard · error

cannot get board %s: %w

Error message

cannot get board %s: %w

What it means

In getBoardForBlock, after the block is loaded, the parent board (block.BoardID) is fetched. This error wraps a failure of App.GetBoard(block.BoardID) — the board that owns the block cannot be retrieved. It indicates the board was deleted while its block still exists, or a store-level error occurred.

Source

Thrown at server/app/boards.go:85

		BoardID:                 boardID,
		DescendantFirstUpdateAt: earliestTime,
		DescendantLastUpdateAt:  latestTime,
		CreatedBy:               board.CreatedBy,
		LastModifiedBy:          lastModifiedBy,
	}
	return board, &boardMetadata, nil
}

// getBoardForBlock returns the board that owns the specified block.
func (a *App) getBoardForBlock(blockID string) (*model.Board, error) {
	block, err := a.GetBlockByID(blockID)
	if err != nil {
		return nil, fmt.Errorf("cannot get block %s: %w", blockID, err)
	}

	board, err := a.GetBoard(block.BoardID)
	if err != nil {
		return nil, fmt.Errorf("cannot get board %s: %w", block.BoardID, err)
	}

	return board, nil
}

func (a *App) getBoardHistory(boardID string, latest bool) (*model.Board, error) {
	opts := model.QueryBoardHistoryOptions{
		Limit:      1,
		Descending: latest,
	}
	boards, err := a.store.GetBoardHistory(boardID, opts)
	if err != nil {
		return nil, fmt.Errorf("could not get history for board: %w", err)
	}
	if len(boards) == 0 {
		return nil, nil
	}

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Unwrap and check for not-found: an orphaned block points to a deleted board — clean up or ignore the notification.
  2. Ensure board deletion cascades to all child blocks so this state cannot occur.
  3. Retry the request if the underlying cause is a transient database error.
  4. Audit the database for blocks whose BoardID has no matching board.
Defensive patterns

Strategy: try-catch

Validate before calling

block, err := app.GetBlockByID(blockID)
if err != nil {
    return err
}
board, err := app.GetBoard(block.BoardID)
if err != nil || board == nil {
    return fmt.Errorf("orphaned block %s: board %s missing", blockID, block.BoardID)
}

Type guard

func hasValidBoard(b *model.Block, board *model.Board) bool {
    return b != nil && board != nil && board.ID == b.BoardID
}

Try / catch

board, err := app.getBoardForBlock(blockID)
if err != nil {
    var nf *NotFoundError
    if errors.As(err, &nf) {
        return nil // parent board deleted; skip notification
    }
    return err
}

Prevention

When it happens

Trigger: notifySubscriptionChanged processes a block whose parent board no longer exists (orphaned block, e.g. board deleted without cascading blocks, or history/orphan rows), or the store returns an error for the board lookup.

Common situations: Data inconsistency after partial board deletion; restore-from-backup scenarios leaving orphan blocks; database outages affecting board reads.

Related errors


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