{"record":{"id":"6206284e90fbd194","repo":"mattermost-community/focalboard","slug":"invalid-property-value-type","errorCode":null,"errorMessage":"invalid property value type","messagePattern":"invalid property value type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/model/properties.go","lineNumber":21,"sourceCode":"\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\"`\n\tIndex int    `json:\"index\"`\n\tName  string `json:\"name\"`\n\tValue string `json:\"value\"`\n}","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/model/properties.go#L3-L39","documentation":"ErrInvalidPropertyValueType is returned when the raw JSON value of a property has a type that does not match the property definition type, e.g. a string where the schema expects an array for multi-select. GetPropertyString and GetValue throw it during type-checked decoding. It prevents type-confusion when reading property values.","triggerScenarios":"Reading a property whose JSON value cannot be cast to the type dictated by PropDef.Type (e.g. number stored as object, select stored as array), via GetValue or GetPropertyString.","commonSituations":"A property's type was changed in cardProperties after cards already stored old-typed values, migrations between versions, or external writes to the DB with mismatched JSON types.","solutions":["Correct the stored value's JSON type to match the property definition type.","Restore the original property type in cardProperties if it was changed unintentionally.","Write a migration to convert old values to the new type after changing a property type.","Use errors.Is(err, model.ErrInvalidPropertyValueType) on reads to skip mismatched values instead of failing."],"exampleFix":"// before: property type changed to multi-select but value is a string\nprops[\"tags\"] = \"urgent\"\n// after: store the array shape the type requires\nprops[\"tags\"] = []string{\"opt_urgent\"}","handlingStrategy":"type-guard","validationCode":"func valueMatchesType(def model.PropDef, raw json.RawMessage) bool {\n    switch def.Type {\n    case \"multiSelect\":\n        var arr []string\n        return json.Unmarshal(raw, &arr) == nil\n    case \"number\":\n        var n float64\n        return json.Unmarshal(raw, &n) == nil\n    default:\n        var s string\n        return json.Unmarshal(raw, &s) == nil\n    }\n}","typeGuard":"func isStringArray(raw json.RawMessage) bool {\n    var arr []string\n    return json.Unmarshal(raw, &arr) == nil\n}","tryCatchPattern":"val, err := GetValue(resolver, board, props, key)\nif errors.Is(err, model.ErrInvalidPropertyValueType) {\n    log.Warn(\"property value type mismatch\", \"key\", key)\n    val = \"\"\n}","preventionTips":["Don't change a property's type while cards still hold old-typed values; migrate values first.","Use typed helpers to write property values instead of raw JSON.","Test schema changes on a copy of the board."],"tags":["go","type-mismatch","properties"],"backgroundTag":"type-mismatch","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}