{"record":{"id":"d8feaa3ecf5f45af","repo":"siyuan-note/siyuan","slug":"each-key-requires-name-and-type","errorCode":null,"errorMessage":"each key requires name and type","messagePattern":"each key requires name and type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/database.go","lineNumber":217,"sourceCode":"\nfunc databaseCreateKeySpecs(value any) (ret []*model.AttributeViewCreateKey, err error) {\n\tif nil == value {\n\t\treturn []*model.AttributeViewCreateKey{}, nil\n\t}\n\titems, ok := value.([]any)\n\tif !ok {\n\t\treturn nil, errors.New(\"keys must be an array\")\n\t}\n\tfor _, item := range items {\n\t\tdata, itemOK := item.(map[string]any)\n\t\tif !itemOK {\n\t\t\treturn nil, errors.New(\"each key must be an object\")\n\t\t}\n\t\tname, _ := data[\"name\"].(string)\n\t\tkeyType, _ := data[\"type\"].(string)\n\t\ticon, _ := data[\"icon\"].(string)\n\t\tif \"\" == strings.TrimSpace(name) || \"\" == strings.TrimSpace(keyType) {\n\t\t\treturn nil, errors.New(\"each key requires name and type\")\n\t\t}\n\t\tret = append(ret, &model.AttributeViewCreateKey{Name: name, Type: keyType, Icon: icon})\n\t}\n\treturn\n}\n\nfunc databaseSuccess(action string, data any) (CallToolResult, error) {\n\toutput := &databaseToolOutput{Action: action, Data: data}\n\tserialized, err := json.Marshal(output)\n\tif nil != err {\n\t\treturn CallToolResult{}, err\n\t}\n\treturn CallToolResult{\n\t\tContent:              []ContentItem{{Type: \"text\", Text: string(serialized)}},\n\t\tStructuredContent:    output,\n\t\tStructuredContentSet: true,\n\t}, nil\n}","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/tools/database.go#L199-L235","documentation":"databaseCreateKeySpecs (kernel/mcp/tools/database.go) requires every key object to carry a non-empty (after trimming) `name` and `type`; a missing or blank one is rejected with this error. Icon is optional and defaults to empty.","triggerScenarios":"Keys like [{\"name\":\"\",\"type\":\"text\"}], [{\"type\":\"text\"}], or [{\"name\":\"  \",\"type\":\"  \"}] passed to the database create MCP tool; type strings not matching a supported attribute-view key type will pass this check but fail later.","commonSituations":"Programmatic key generation leaving name empty when the header cell is blank; typos in the field name (e.g. \"label\" instead of \"name\"); LLM-generated specs omitting type.","solutions":["Ensure every key object has non-empty name and type strings","Check for misspelled property names in the key object (name/type vs label/kind)","Trim whitespace in names/types client-side and reject blanks before the call","Use one of the supported key types (text, number, date, select, mSelect, etc.)"],"exampleFix":"// before\nkeys: [{type: \"text\"}]\n// after\nkeys: [{name: \"Title\", type: \"text\"}]","handlingStrategy":"validation","validationCode":"const ok = keys.every(k => typeof k?.name === \"string\" && k.name.trim() && typeof k?.type === \"string\" && k.type.trim());","typeGuard":"const hasNameAndType = (k) => !!(k?.name?.trim() && k?.type?.trim());","tryCatchPattern":null,"preventionTips":["Require name and type on every key spec","Trim whitespace before sending","Check for typo'd property names"],"tags":["mcp","database","validation","missing-field"],"backgroundTag":"empty-required-field","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"}