mattermost-community/focalboard · error

could not get blocks history descendants for board: %w

Error message

could not get blocks history descendants for board: %w

What it means

After reading board history, getBoardDescendantModifiedInfo queries the newest history entry among all descendant blocks via store.GetBlockHistoryDescendants. This error wraps a failure of that store call while computing the board's effective last-modified timestamp.

Source

Thrown at server/app/boards.go:131

		return 0, "", fmt.Errorf("history not found for board: %w", err)
	}

	var timestamp int64
	modifiedBy := board.ModifiedBy
	if latest {
		timestamp = board.UpdateAt
	} else {
		timestamp = board.CreateAt
	}

	// use block_history to fetch blocks in case they were deleted and no longer exist in blocks table.
	opts := model.QueryBlockHistoryOptions{
		Limit:      1,
		Descending: latest,
	}
	blocks, err := a.store.GetBlockHistoryDescendants(boardID, opts)
	if err != nil {
		return 0, "", fmt.Errorf("could not get blocks history descendants for board: %w", err)
	}
	if len(blocks) > 0 {
		// Compare the board history info with the descendant block info, if it exists
		block := blocks[0]
		if latest && block.UpdateAt > timestamp {
			timestamp = block.UpdateAt
			modifiedBy = block.ModifiedBy
		} else if !latest && block.CreateAt < timestamp {
			timestamp = block.CreateAt
			modifiedBy = block.ModifiedBy
		}
	}
	return timestamp, modifiedBy, nil
}

func (a *App) setBoardCategoryFromSource(sourceBoardID, destinationBoardID, userID, teamID string, asTemplate bool) error {
	// find source board's category ID for the user
	userCategoryBoards, err := a.GetUserCategoryBoards(userID, teamID)

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Inspect the wrapped store error; check DB logs for query timeouts on block history.
  2. Confirm block-history storage (indexes/collections) exists and is migrated.
  3. Retry transient failures; consider caching metadata for large boards.
  4. Verify boardID is a valid board with existing descendants.
Defensive patterns

Strategy: retry

Validate before calling

if _, err := app.GetBoard(boardID); err != nil {
    return fmt.Errorf("board %s must exist before descendant history query", boardID)
}

Try / catch

meta, err := app.GetBoardMetadata(boardID, latest)
if err != nil {
    if strings.Contains(err.Error(), "could not get blocks history descendants") && isTransient(err) {
        return retryWithBackoff(func() error { _, err = app.GetBoardMetadata(boardID, latest); return err })
    }
    return err
}

Prevention

When it happens

Trigger: GetBoardMetadata on a board with many descendant blocks where the store query fails: database timeout, index/collection missing for block history, or oversized descendant query exceeding DB limits.

Common situations: Very large boards causing slow/failed descendant history queries; block-history collections dropped or not migrated; transient database outages during metadata loads.

Related errors


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