{"record":{"id":"f5088f060a7c3abf","repo":"mattermost-community/focalboard","slug":"cannot-get-board-s-w","errorCode":null,"errorMessage":"cannot get board %s: %w","messagePattern":"cannot get board (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/app/boards.go","lineNumber":85,"sourceCode":"\t\tBoardID:                 boardID,\n\t\tDescendantFirstUpdateAt: earliestTime,\n\t\tDescendantLastUpdateAt:  latestTime,\n\t\tCreatedBy:               board.CreatedBy,\n\t\tLastModifiedBy:          lastModifiedBy,\n\t}\n\treturn board, &boardMetadata, nil\n}\n\n// getBoardForBlock returns the board that owns the specified block.\nfunc (a *App) getBoardForBlock(blockID string) (*model.Board, error) {\n\tblock, err := a.GetBlockByID(blockID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot get block %s: %w\", blockID, err)\n\t}\n\n\tboard, err := a.GetBoard(block.BoardID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot get board %s: %w\", block.BoardID, err)\n\t}\n\n\treturn board, nil\n}\n\nfunc (a *App) getBoardHistory(boardID string, latest bool) (*model.Board, error) {\n\topts := model.QueryBoardHistoryOptions{\n\t\tLimit:      1,\n\t\tDescending: latest,\n\t}\n\tboards, err := a.store.GetBoardHistory(boardID, opts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not get history for board: %w\", err)\n\t}\n\tif len(boards) == 0 {\n\t\treturn nil, nil\n\t}\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/app/boards.go#L67-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"Data inconsistency after partial board deletion; restore-from-backup scenarios leaving orphan blocks; database outages affecting board reads.","solutions":["Unwrap and check for not-found: an orphaned block points to a deleted board — clean up or ignore the notification.","Ensure board deletion cascades to all child blocks so this state cannot occur.","Retry the request if the underlying cause is a transient database error.","Audit the database for blocks whose BoardID has no matching board."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"block, err := app.GetBlockByID(blockID)\nif err != nil {\n    return err\n}\nboard, err := app.GetBoard(block.BoardID)\nif err != nil || board == nil {\n    return fmt.Errorf(\"orphaned block %s: board %s missing\", blockID, block.BoardID)\n}","typeGuard":"func hasValidBoard(b *model.Block, board *model.Board) bool {\n    return b != nil && board != nil && board.ID == b.BoardID\n}","tryCatchPattern":"board, err := app.getBoardForBlock(blockID)\nif err != nil {\n    var nf *NotFoundError\n    if errors.As(err, &nf) {\n        return nil // parent board deleted; skip notification\n    }\n    return err\n}","preventionTips":["Ensure board deletion cascades to child blocks so orphan blocks cannot exist.","Run periodic integrity checks for blocks referencing missing boards.","Retry only on transient store errors, not on not-found."],"tags":["board","lookup","orphaned-block","wrapped-error"],"backgroundTag":"board-not-found","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}