{"record":{"id":"b44c43086a2ec5fa","repo":"mattermost-community/focalboard","slug":"invalid-board-block","errorCode":null,"errorMessage":"invalid board block","messagePattern":"invalid board block","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/model/properties.go","lineNumber":17,"sourceCode":"// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n// See LICENSE.txt for license information.\n\n//go:generate mockgen -destination=mocks/propValueResolverMock.go -package mocks . PropValueResolver\n\npackage model\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/mattermost/focalboard/server/utils\"\n)\n\nvar ErrInvalidBoardBlock = errors.New(\"invalid board block\")\nvar ErrInvalidPropSchema = errors.New(\"invalid property schema\")\nvar ErrInvalidProperty = errors.New(\"invalid property\")\nvar ErrInvalidPropertyValue = errors.New(\"invalid property value\")\nvar ErrInvalidPropertyValueType = errors.New(\"invalid property value type\")\nvar ErrInvalidDate = errors.New(\"invalid date property\")\n\n// PropValueResolver allows PropDef.GetValue to further decode property values, such as\n// looking up usernames from ids.\ntype PropValueResolver interface {\n\tGetUserByID(userID string) (*User, error)\n}\n\n// BlockProperties is a map of Prop's keyed by property id.\ntype BlockProperties map[string]BlockProp\n\n// BlockProp represent a property attached to a block (typically a card).\ntype BlockProp struct {\n\tID    string `json:\"id\"`","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/model/properties.go#L1-L35","documentation":"ErrInvalidBoardBlock signals that a block payload being imported does not represent a valid board. It is declared as a sentinel error in server/model/properties.go and wrapped by ImportBoardJSONL when the JSONL archive lacks a board block. The library throws it to abort imports early instead of persisting a malformed archive.","triggerScenarios":"Calling ImportBoardJSONL with an archive whose JSONL stream contains no block of type 'board', or where the board entry fails block validation, producing 'missing board in archive: %w' wrapping this sentinel.","commonSituations":"Importing a hand-edited or truncated export file, importing an archive exported from a different product/version whose schema differs, or uploading an empty/partial JSONL file through the bulk import API.","solutions":["Re-export the board from Focalboard so the archive contains a valid board block as its first/required entry.","Inspect the JSONL file and confirm a line with type \"board\" exists and is valid JSON.","Do not hand-edit export archives; if edits are needed, validate the JSON afterwards with a schema/linter.","Check that you are importing an archive of the matching format/version for your Focalboard release."],"exampleFix":"// before: importing a truncated export\nblocks, err := app.ImportBoardJSONL(teamID, modifiedBy, r.Body)\n// after: validate the archive contains a board line first\nif !strings.Contains(archiveContent, \"\\\"type\\\":\\\"board\\\"\") {\n    return errors.New(\"archive does not contain a board block\")\n}\nblocks, err := app.ImportBoardJSONL(teamID, modifiedBy, r.Body)","handlingStrategy":"validation","validationCode":"// check archive has a board block before import\nlines := strings.Split(archiveContent, \"\\n\")\nhasBoard := false\nfor _, l := range lines {\n    var b map[string]interface{}\n    if json.Unmarshal([]byte(l), &b) == nil && b[\"type\"] == \"board\" {\n        hasBoard = true\n        break\n    }\n}\nif !hasBoard {\n    return errors.New(\"archive contains no board block\")\n}","typeGuard":"func isValidBoardBlock(raw []byte) bool {\n    var b struct{ Type string `json:\"type\"` }\n    return json.Unmarshal(raw, &b) == nil && b.Type == \"board\"\n}","tryCatchPattern":"blocks, err := app.ImportBoardJSONL(teamID, userID, r.Body)\nif errors.Is(err, model.ErrInvalidBoardBlock) {\n    http.Error(w, \"archive is missing a valid board block\", http.StatusBadRequest)\n    return\n}","preventionTips":["Only import archives produced by Focalboard's own export.","Never hand-edit JSONL export files without re-validating.","Keep export/import formats version-matched between instances."],"tags":["go","import","data-validation"],"backgroundTag":"invalid-import-archive","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}