{"record":{"id":"a75e75b6f70f78c5","repo":"flipped-aurora/gin-vue-admin","slug":"packageinfo-packagename","errorCode":null,"errorMessage":"packageInfo.packageName 不能为空","messagePattern":"packageInfo\\.packageName 不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mcp/gva_execute.go","lineNumber":306,"sourceCode":"// validateExecutionPlan 验证执行计划的完整性\nfunc (g *GVAExecutor) validateExecutionPlan(ctx context.Context, plan *ExecutionPlan) error {\n\tif plan.PackageName == \"\" {\n\t\treturn errors.New(\"packageName 不能为空\")\n\t}\n\tif plan.PackageType != \"package\" && plan.PackageType != \"plugin\" {\n\t\treturn errors.New(\"packageType 必须是 'package' 或 'plugin'\")\n\t}\n\n\tif plan.NeedCreatedPackage && plan.PackageInfo != nil && plan.PackageType != plan.PackageInfo.Template {\n\t\treturn errors.New(\"packageType 和 packageInfo.template 必须保持一致\")\n\t}\n\n\tif plan.NeedCreatedPackage {\n\t\tif plan.PackageInfo == nil {\n\t\t\treturn errors.New(\"当 needCreatedPackage=true 时，packageInfo 不能为空\")\n\t\t}\n\t\tif plan.PackageInfo.PackageName == \"\" {\n\t\t\treturn errors.New(\"packageInfo.packageName 不能为空\")\n\t\t}\n\t\tif plan.PackageInfo.Template != \"package\" && plan.PackageInfo.Template != \"plugin\" {\n\t\t\treturn errors.New(\"packageInfo.template 必须是 'package' 或 'plugin'\")\n\t\t}\n\t\tif plan.PackageInfo.Label == \"\" {\n\t\t\treturn errors.New(\"packageInfo.label 不能为空\")\n\t\t}\n\t\tif plan.PackageInfo.Desc == \"\" {\n\t\t\treturn errors.New(\"packageInfo.desc 不能为空\")\n\t\t}\n\t}\n\n\tif plan.NeedCreatedModules {\n\t\tif len(plan.ModulesInfo) == 0 {\n\t\t\treturn errors.New(\"当 needCreatedModules=true 时，modulesInfo 不能为空\")\n\t\t}\n\n\t\tfor moduleIndex, moduleInfo := range plan.ModulesInfo {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/mcp/gva_execute.go#L288-L324","documentation":"Inside the NeedCreatedPackage block, validateExecutionPlan checks each required packageInfo field. The nested PackageInfo.PackageName must be non-empty; it is the name used when actually generating the new package/plugin and can differ from the top-level packageName. An empty nested name would produce an unnamed artifact.","triggerScenarios":"executionPlan with needCreatedPackage=true, packageInfo present, but packageInfo.packageName is \"\" or omitted (top-level packageName alone does not satisfy this check).","commonSituations":"Assuming the top-level packageName propagates into packageInfo; constructing packageInfo with only template/label/desc; form data where the name input was left blank.","solutions":["Set packageInfo.packageName to the new package/plugin's name.","Or copy the top-level packageName into packageInfo if they should be the same.","Confirm JSON key casing (`packageName`) so it binds to the struct field.","Validate all required packageInfo fields client-side before invoking."],"exampleFix":"// before\npackageInfo: { template: \"plugin\", label: \"订单中心\", desc: \"...\" }\n\n// after\npackageInfo: { packageName: \"order-center\", template: \"plugin\", label: \"订单中心\", desc: \"...\" }","handlingStrategy":"validation","validationCode":"function requireNestedPackageName(plan) {\n  if (plan.needCreatedPackage && (!plan.packageInfo || !plan.packageInfo.packageName?.trim())) {\n    throw new Error('packageInfo.packageName is required when needCreatedPackage=true');\n  }\n  return plan;\n}","typeGuard":"function hasNestedPackageName(plan) {\n  return !plan.needCreatedPackage || (typeof plan.packageInfo?.packageName === 'string' && plan.packageInfo.packageName.trim().length > 0);\n}","tryCatchPattern":"try {\n  return await callTool('gva_execute', { executionPlan: plan });\n} catch (err) {\n  if (String(err.message).includes('packageInfo.packageName 不能为空')) {\n    plan.packageInfo.packageName = plan.packageName; // default from top-level name\n    return callTool('gva_execute', { executionPlan: plan });\n  }\n  throw err;\n}","preventionTips":["Do not assume top-level packageName propagates — set packageInfo.packageName explicitly","Build packageInfo with all required fields via a helper that takes name/template/label/desc","Keep JSON key casing camelCase to match the Go struct tags"],"tags":["mcp","validation","go","execution-plan"],"backgroundTag":"missing-required-field","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}