mattermost-community/focalboard · error

history not found for board: %w

Error message

history not found for board: %w

What it means

getBoardDescendantModifiedInfo treats a nil result from getBoardHistory as 'no history rows exist for this board' and returns 'history not found for board'. As written it wraps err, which is nil at that point, so the formatted message contains '%!w(<nil>)'; the semantic meaning is that the board has no history entries at all.

Source

Thrown at server/app/boards.go:113

	}
	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
	}

	return boards[0], nil
}

func (a *App) getBoardDescendantModifiedInfo(boardID string, latest bool) (int64, string, error) {
	board, err := a.getBoardHistory(boardID, latest)
	if err != nil {
		return 0, "", err
	}
	if board == nil {
		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)

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Treat missing history as empty metadata on the caller side instead of an error, if acceptable for your use case.
  2. Create/update the board once through the app API so a history row is generated.
  3. Backfill history rows for legacy boards via a migration.
  4. Fix the source bug: return a dedicated sentinel (e.g. ErrHistoryNotFound) rather than wrapping nil err.

Example fix

// before
if board == nil {
    return 0, "", fmt.Errorf("history not found for board: %w", err)
}
// after
if board == nil {
    return 0, "", ErrBoardHistoryNotFound
}
Defensive patterns

Strategy: fallback

Validate before calling

// detect the missing-history condition up front
_, err := app.GetBoard(boardID)
if err != nil {
    return err
}
// no way to pre-check history rows via public API; fall back on error

Try / catch

meta, err := app.GetBoardMetadata(boardID, latest)
if err != nil {
    if strings.Contains(err.Error(), "history not found for board") {
        meta = &model.BoardMetadata{} // fall back to empty metadata
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: GetBoardMetadata (via getBoardDescendantModifiedInfo) on a board that has never had a history record inserted — e.g. boards created before history tracking existed, boards created directly in the DB, or newly created boards whose first history row has not been written.

Common situations: Legacy data predating the board-history feature; imports/migrations that skipped history; a bug where board creation does not seed a history entry.

Related errors


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