siyuan-note/siyuan · error
each key requires name and type
Error message
each key requires name and type
What it means
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.
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.)
Example fix
// before
keys: [{type: "text"}]
// after
keys: [{name: "Title", type: "text"}] Defensive patterns
Strategy: validation
Validate before calling
const ok = keys.every(k => typeof k?.name === "string" && k.name.trim() && typeof k?.type === "string" && k.type.trim());
Type guard
const hasNameAndType = (k) => !!(k?.name?.trim() && k?.type?.trim());
Prevention
- Require name and type on every key spec
- Trim whitespace before sending
- Check for typo'd property names
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- each key must be an object
- keys must be an array
- prev must be a string
- attr must be a string or null (got %T)
- --av and --ids are required
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/d8feaa3ecf5f45af.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/tools/database.go:217
func databaseCreateKeySpecs(value any) (ret []*model.AttributeViewCreateKey, err error) {
if nil == value {
return []*model.AttributeViewCreateKey{}, nil
}
items, ok := value.([]any)
if !ok {
return nil, errors.New("keys must be an array")
}
for _, item := range items {
data, itemOK := item.(map[string]any)
if !itemOK {
return nil, errors.New("each key must be an object")
}
name, _ := data["name"].(string)
keyType, _ := data["type"].(string)
icon, _ := data["icon"].(string)
if "" == strings.TrimSpace(name) || "" == strings.TrimSpace(keyType) {
return nil, errors.New("each key requires name and type")
}
ret = append(ret, &model.AttributeViewCreateKey{Name: name, Type: keyType, Icon: icon})
}
return
}
func databaseSuccess(action string, data any) (CallToolResult, error) {
output := &databaseToolOutput{Action: action, Data: data}
serialized, err := json.Marshal(output)
if nil != err {
return CallToolResult{}, err
}
return CallToolResult{
Content: []ContentItem{{Type: "text", Text: string(serialized)}},
StructuredContent: output,
StructuredContentSet: true,
}, nil
}View on GitHub (pinned to 9f775e8a12)