mattermost-community/focalboard · error

not a card block

Error message

not a card block

What it means

ErrNotCardBlock is a sentinel error in the Mattermost Boards model package indicating that a block was expected to be a card-type block but was not. Block2Card converts a generic Block into a Card and throws this when the block's Type is not TypeCard. It guards against silently misinterpreting non-card blocks (e.g. boards, text blocks) as cards.

Source

Thrown at server/model/card.go:27

)

var ErrBoardIDMismatch = errors.New("Board IDs do not match")

type ErrInvalidCard struct {
	msg string
}

func NewErrInvalidCard(msg string) ErrInvalidCard {
	return ErrInvalidCard{
		msg: msg,
	}
}

func (e ErrInvalidCard) Error() string {
	return fmt.Sprintf("invalid card, %s", e.msg)
}

var ErrNotCardBlock = errors.New("not a card block")

type ErrInvalidFieldType struct {
	field string
}

func (e ErrInvalidFieldType) Error() string {
	return fmt.Sprintf("invalid type for field '%s'", e.field)
}

// Card represents a group of content blocks and properties.
// swagger:model
type Card struct {
	// The id for this card
	// required: false
	ID string `json:"id"`

	// The id for board this card belongs to.
	// required: false

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Verify the Block.Type equals model.TypeCard before calling Block2Card
  2. Filter the block list to only card-type blocks before conversion
  3. Check whether the API that produced the block was queried with the correct block type

Example fix

// before
card := model.Block2Card(block)
// after
if block.Type != model.TypeCard {
    return nil, fmt.Errorf("block %s is %s, not a card", block.ID, block.Type)
}
card := model.Block2Card(block)
Defensive patterns

Strategy: validation

Validate before calling

if block.Type != model.TypeCard {
    // handle or skip: not convertible to a card
    return fmt.Errorf("block %s is not a card", block.ID)
}

Type guard

func isCardBlock(b model.Block) bool {
    return b.Type == model.TypeCard
}

Try / catch

card, err := model.Block2Card(block)
if err != nil {
    if errors.Is(err, model.ErrNotCardBlock) {
        continue // skip non-card block
    }
    return err
}

Prevention

When it happens

Trigger: Calling Block2Card with a Block whose Type field is not 'card' — e.g. passing a board block, text block, or image block loaded from the database or an import archive.

Common situations: Importing/archiving boards where blocks were mixed; queries that fetch blocks by parent ID without filtering type; refactors that assume a returned slice contains only cards.

Related errors


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