{"record":{"id":"961e109fb438f9b0","repo":"mattermost-community/focalboard","slug":"insertboard-error-occurred-while-updating-existing","errorCode":null,"errorMessage":"insertBoard error occurred while updating existing board %s: %w","messagePattern":"insertBoard error occurred while updating existing board (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/sqlstore/board.go","lineNumber":380,"sourceCode":"\t\t\tWhere(sq.Eq{\"id\": board.ID}).\n\t\t\tSet(\"modified_by\", board.ModifiedBy).\n\t\t\tSet(\"type\", board.Type).\n\t\t\tSet(\"channel_id\", board.ChannelID).\n\t\t\tSet(\"minimum_role\", board.MinimumRole).\n\t\t\tSet(\"title\", board.Title).\n\t\t\tSet(\"description\", board.Description).\n\t\t\tSet(\"icon\", board.Icon).\n\t\t\tSet(\"show_description\", board.ShowDescription).\n\t\t\tSet(\"is_template\", board.IsTemplate).\n\t\t\tSet(\"template_version\", board.TemplateVersion).\n\t\t\tSet(\"properties\", propertiesBytes).\n\t\t\tSet(\"card_properties\", cardPropertiesBytes).\n\t\t\tSet(\"update_at\", board.UpdateAt).\n\t\t\tSet(\"delete_at\", board.DeleteAt)\n\n\t\tif _, err := query.Exec(); err != nil {\n\t\t\ts.logger.Error(`InsertBoard error occurred while updating existing board`, mlog.String(\"boardID\", board.ID), mlog.Err(err))\n\t\t\treturn nil, fmt.Errorf(\"insertBoard error occurred while updating existing board %s: %w\", board.ID, err)\n\t\t}\n\t} else {\n\t\tboard.CreatedBy = userID\n\t\tboard.CreateAt = now\n\t\tinsertQueryValues[\"created_by\"] = board.CreatedBy\n\t\tinsertQueryValues[\"create_at\"] = board.CreateAt\n\n\t\tquery := insertQuery.SetMap(insertQueryValues).Into(s.tablePrefix + \"boards\")\n\t\tif _, err := query.Exec(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"insertBoard error occurred while inserting board %s: %w\", board.ID, err)\n\t\t}\n\t}\n\n\t// writing board history\n\tquery := insertQuery.SetMap(insertQueryValues).Into(s.tablePrefix + \"boards_history\")\n\tif _, err := query.Exec(); err != nil {\n\t\ts.logger.Error(\"failed to insert board history\", mlog.String(\"board_id\", board.ID), mlog.Err(err))\n\t\treturn nil, fmt.Errorf(\"failed to insert board %s history: %w\", board.ID, err)","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/sqlstore/board.go#L362-L398","documentation":"When a board with the same ID already exists, insertBoard updates the existing row instead of inserting; if that UPDATE Exec fails, this error is returned (the failure is also logged server-side with the board ID). It wraps the raw driver error, so the real cause (constraint violation, lock timeout, connection loss) is in the wrapped err.","triggerScenarios":"InsertBoard/patchBoard/createBoardsAndBlocks/insertBoardWithAdmin hitting the update path where a board with board.ID exists, and the UPDATE fails — e.g. deadlocks, lock waits, constraint failures on card_properties JSON, or connection drops.","commonSituations":"Concurrent edits causing row lock contention; oversized/invalid card_properties data exceeding DB limits; connection pool exhaustion under load; MySQL strict-mode rejecting data types.","solutions":["Check server logs for the paired 'InsertBoard error occurred while updating existing board' entry with the driver error detail","Inspect the wrapped err: lock/timeout issues → reduce concurrency or add retries; constraint issues → fix the payload","Verify card_properties bytes are valid JSON within DB column limits","Ensure the DB connection pool settings match your load (max open/idle connections)"],"exampleFix":"// before\ninsertBoard(board) // retries not configured, fails under lock contention\n// after\nfor i := 0; i < 3; i++ {\n    _, err := insertBoard(board)\n    if err == nil || !isDeadlock(err) {\n        break\n    }\n    time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)\n}","handlingStrategy":"retry","validationCode":"func isRetryableDBError(err error) bool {\n    if err == nil { return false }\n    s := err.Error()\n    return strings.Contains(s, \"Deadlock\") || strings.Contains(s, \"Lock wait timeout\") || strings.Contains(s, \"connection\")\n}","typeGuard":null,"tryCatchPattern":"board, err := store.InsertBoard(board, userID)\nif err != nil && strings.Contains(err.Error(), \"error occurred while updating existing board\") {\n    if isRetryableDBError(err) {\n        board, err = store.InsertBoard(board, userID) // safe: same board ID, idempotent update\n    }\n}","preventionTips":["Limit concurrent writes to the same board to reduce lock contention","Keep card_properties JSON within column size limits","Match DB pool sizing to workload to avoid lock pile-ups","Run MySQL in a mode compatible with the server's expected data types"],"tags":["database","update","upsert","concurrency"],"backgroundTag":"board-update-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}