{"record":{"id":"edcdfa4d784c0b4f","repo":"flipped-aurora/gin-vue-admin","slug":"apis-json","errorCode":null,"errorMessage":"apis 需为JSON数组或逗号分隔字符串","messagePattern":"apis 需为JSON数组或逗号分隔字符串","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mcp/role_api_batch_assigner.go","lineNumber":182,"sourceCode":"\t\t// 形如 [{\"path\":..,\"method\":..}] 若按逗号切分会碎成垃圾策略,先尝试按 JSON 数组解析\n\t\tif strings.HasPrefix(trimmed, \"[\") {\n\t\t\tvar arr []any\n\t\t\tif err := json.Unmarshal([]byte(trimmed), &arr); err == nil {\n\t\t\t\treturn parseAPIItems(arr)\n\t\t\t}\n\t\t}\n\t\tfor part := range strings.SplitSeq(trimmed, \",\") {\n\t\t\tif strings.TrimSpace(part) == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, method, err := parseAPIItemString(part)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tappendItem(path, method)\n\t\t}\n\tdefault:\n\t\treturn nil, errors.New(\"apis 需为JSON数组或逗号分隔字符串\")\n\t}\n\n\t// 批内去重(按归一化后的 path+method)\n\tseen := make(map[string]struct{}, len(items))\n\tdeduped := items[:0]\n\tfor _, item := range items {\n\t\tpath, method := normalizePolicy(item.Path, item.Method)\n\t\tkey := method + \" \" + path\n\t\tif _, ok := seen[key]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseen[key] = struct{}{}\n\t\tdeduped = append(deduped, item)\n\t}\n\treturn deduped, nil\n}\n\n// parseAPIItemString 解析\"METHOD /path\"或\"/path\"形式的单条API,方法缺省为POST","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/mcp/role_api_batch_assigner.go#L164-L200","documentation":"parseAPIItems in role_api_batch_assigner.go accepts the `apis` input as either a JSON array of {path,method} objects or a comma-separated string of path:method items. It throws this error when the input is neither — i.e. the parsed value is not a []interface{} array and not a string, so it falls into the default branch. It is a strict input-format validation guard before path+method items are normalized and deduplicated.","triggerScenarios":"Calling the batch-assign Handle flow with apis as a bare object (e.g. {\"path\":\"/x\",\"method\":\"GET\"} without array wrapping), a number, boolean, or null. Also when the client sends form data or a nested structure instead of a JSON array string like '[{\"path\":\"/a\",\"method\":\"GET\"}]' or 'path1:GET,path2:POST'.","commonSituations":"Frontend code passing the wrong shape after refactoring (single object instead of array); API consumers omitting the field wrapper when only one API is assigned; hand-rolled curl calls guessing the format; template/generated code sending an object keyed by path.","solutions":["Send apis as a JSON array of {path, method} objects: apis=[{\"path\":\"/user/list\",\"method\":\"GET\"}]","Or send a comma-separated string of path:method items: apis=/user/list:GET,/user/create:POST","Check the request content-type / field encoding — ensure the value is not being double-wrapped or coerced into an object by the client serializer","Add client-side validation that rejects non-array, non-string apis values before submission"],"exampleFix":"// before\n{ \"apis\": { \"path\": \"/user/list\", \"method\": \"GET\" } }\n// after\n{ \"apis\": [ { \"path\": \"/user/list\", \"method\": \"GET\" } ] }\n// or\n{ \"apis\": \"/user/list:GET\" }","handlingStrategy":"validation","validationCode":"const apis = payload.apis\nconst isJsonArray = Array.isArray(apis) || (typeof apis === 'string' && apis.trim().startsWith('['))\nconst isCsv = typeof apis === 'string' && /:?[A-Za-z]+\\s*,/.test(apis)\nif (!isJsonArray && !isCsv) throw new Error('apis must be a JSON array or comma-separated path:method string')","typeGuard":"function isValidApis(v) {\n  if (Array.isArray(v)) return v.every(i => i && typeof i.path === 'string' && typeof i.method === 'string')\n  return typeof v === 'string'\n}","tryCatchPattern":"try {\n  await assignRoleApis({ apis })\n} catch (e) {\n  if (String(e.message).includes('JSON数组或逗号分隔')) {\n    console.error('apis format invalid, use [{path,method}] or \"path:METHOD,...\"', e)\n  } else { throw e }\n}","preventionTips":["Always send apis as an array of {path, method} objects from typed clients","Unit-test the request builder to assert the apis shape before send","Document the two accepted formats in the API client code"],"tags":["mcp","input-validation","request-format"],"backgroundTag":"invalid-request-payload-format","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}