{"record":{"id":"df9aed8ab60e6dd1","repo":"flipped-aurora/gin-vue-admin","slug":"options-df9aed","errorCode":null,"errorMessage":"options 不能为空","messagePattern":"options 不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mcp/dictionary_generator.go","lineNumber":87,"sourceCode":"\tdictType, ok := args[\"dictType\"].(string)\n\tif !ok || dictType == \"\" {\n\t\treturn nil, errors.New(\"dictType 参数是必需的\")\n\t}\n\tfieldDesc, ok := args[\"fieldDesc\"].(string)\n\tif !ok || fieldDesc == \"\" {\n\t\treturn nil, errors.New(\"fieldDesc 参数是必需的\")\n\t}\n\toptionsStr, ok := args[\"options\"].(string)\n\tif !ok || optionsStr == \"\" {\n\t\treturn nil, errors.New(\"options 参数是必需的\")\n\t}\n\n\tvar options []DictionaryOption\n\tif err := json.Unmarshal([]byte(optionsStr), &options); err != nil {\n\t\treturn nil, fmt.Errorf(\"options 参数格式错误: %v\", err)\n\t}\n\tif len(options) == 0 {\n\t\treturn nil, errors.New(\"options 不能为空\")\n\t}\n\n\treq := &DictionaryGenerateRequest{\n\t\tDictType:    dictType,\n\t\tFieldDesc:   fieldDesc,\n\t\tOptions:     options,\n\t\tDictName:    stringValue(args[\"dictName\"]),\n\t\tDescription: stringValue(args[\"description\"]),\n\t}\n\n\tresult, err := d.createDictionaryWithOptions(ctx, req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn textResultWithJSON(\"字典选项生成结果：\", result)\n}\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/mcp/dictionary_generator.go#L69-L105","documentation":"Thrown by DictionaryOptionsGenerator's Handle after successfully unmarshalling the options JSON string when the resulting []DictionaryOption slice is empty (len(options) == 0). A dictionary generator cannot produce options from an empty list, so the call is rejected.","triggerScenarios":"Passing \"options\": \"[]\" (valid JSON but zero entries) to dictionary_generator; a JSON string like \"null\" which unmarshals to a nil slice.","commonSituations":"Upstream templating rendering an empty options list; callers filtering all entries out before sending; agents sending placeholder empty arrays to test the tool.","solutions":["Provide at least one {label, value} entry in the options JSON string.","Fix upstream logic that filters or serializes options to an empty array.","Validate options client-side and skip the tool call when the list is empty."],"exampleFix":"// before\n{\"arguments\": {\"dictType\": \"sys_user_status\", \"fieldDesc\": \"用户状态\", \"options\": \"[]\"}}\n// after\n{\"arguments\": {\"dictType\": \"sys_user_status\", \"fieldDesc\": \"用户状态\", \"options\": \"[{\\\"label\\\":\\\"启用\\\",\\\"value\\\":1},{\\\"label\\\":\\\"禁用\\\",\\\"value\\\":2}]\"}}","handlingStrategy":"validation","validationCode":"const parsed = JSON.parse(args.options)\nif (!Array.isArray(parsed) || parsed.length === 0) {\n  throw new Error(\"options must contain at least one {label, value} entry\")\n}","typeGuard":"function hasNonEmptyOptions(args) {\n  try {\n    const parsed = JSON.parse(args.options)\n    return Array.isArray(parsed) && parsed.length > 0 &&\n      parsed.every(o => typeof o.label === \"string\" && \"value\" in o)\n  } catch {\n    return false\n  }\n}","tryCatchPattern":"try {\n  await callTool(\"dictionary_generator\", { dictType, fieldDesc, options })\n} catch (e) {\n  if (e.message.includes(\"options 不能为空\")) {\n    // gather real option entries before retrying\n  }\n}","preventionTips":["Guard against \"[]\" and \"null\" option payloads upstream.","Only call dictionary_generator when at least one option entry exists.","Ensure filtering logic does not silently empty the options list."],"tags":["mcp","empty-input","dictionary"],"backgroundTag":"empty-payload-rejected","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}