{"record":{"id":"7621b25fc8829c9c","repo":"siyuan-note/siyuan","slug":"invalid-database-option-name","errorCode":null,"errorMessage":"invalid database option name","messagePattern":"invalid database option name","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_option_undo.go","lineNumber":171,"sourceCode":"\treturn nil\n}\n\nfunc removeAttributeViewColumnOption(operation *Operation) (err error) {\n\ttx := &Transaction{trees: map[string]*parse.Tree{}}\n\tdefer func() { tx.finishAttributeViewMutation(err != nil) }()\n\treturn tx.mutateAttributeViewOption(operation, true)\n}\n\nfunc updateAttributeViewColumnOption(operation *Operation) (err error) {\n\ttx := &Transaction{trees: map[string]*parse.Tree{}}\n\tdefer func() { tx.finishAttributeViewMutation(err != nil) }()\n\treturn tx.mutateAttributeViewOption(operation, false)\n}\n\nfunc removeAttributeViewColumnOptionValues(attrView *av.AttributeView, operation *Operation) (err error) {\n\toptName, ok := operation.Data.(string)\n\tif !ok {\n\t\treturn errors.New(\"invalid database option name\")\n\t}\n\n\tkey, err := attrView.GetKey(operation.ID)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tfor i, opt := range key.Options {\n\t\tif optName == opt.Name {\n\t\t\tkey.Options = append(key.Options[:i], key.Options[i+1:]...)\n\t\t\tbreak\n\t\t}\n\t}\n\tattrView.RemoveNewItemTemplateSelectOption(operation.ID, optName)\n\n\tfor _, keyValues := range attrView.KeyValues {\n\t\tif keyValues.Key.ID != operation.ID {\n\t\t\tcontinue","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_option_undo.go#L153-L189","documentation":"removeAttributeViewColumnOptionValues expects operation.Data to be a string naming the select-option to remove from a database column. If the type assertion fails (Data is not a string), it returns this sentinel error, because without a valid option name the removal cannot proceed.","triggerScenarios":"Calling the undo/redo mutation path (mutateAttributeViewOption with remove-option operation) when operation.Data was marshalled/stored as a non-string (e.g. an object, map, or nil from a malformed operation payload).","commonSituations":"Undo/redo replaying operations persisted by an older version that stored option data as an object; plugins pushing hand-crafted Operation payloads with wrong Data type; JSON round-trip losing the string.","solutions":["Verify operation.Data is a plain string holding the option name before dispatching the operation","Fix the producer of the Operation to set Data to the option name string","If replaying old history, migrate/normalize old operation payloads to the current format"],"exampleFix":"// before\nconst op = { action: \"removeAttributeViewColumnOptionValues\", id: keyID, data: { name: \"todo\" } }\n// after\nconst op = { action: \"removeAttributeViewColumnOptionValues\", id: keyID, data: \"todo\" }","handlingStrategy":"validation","validationCode":"if typeof op.data !== \"string\" || op.data.length === 0 { throw new Error(\"option name must be a non-empty string\") }","typeGuard":null,"tryCatchPattern":"err := mutateAttributeViewOption(op)\nif err != nil && err.Error() == \"invalid database option name\" {\n    // op.Data was not a string; normalize and retry\n}","preventionTips":["Always serialize operation.Data as a plain string for option mutations","Test undo/redo across version upgrades with old persisted operations","Validate operation payloads before enqueueing them into the mutation queue"],"tags":["type-assertion","undo-redo","attribute-view"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}