{"record":{"id":"28b3f1ed38fed955","repo":"flipped-aurora/gin-vue-admin","slug":"invalid-plugin-type","errorCode":null,"errorMessage":"invalid plugin type","messagePattern":"invalid plugin type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_plugin.go","lineNumber":902,"sourceCode":"\t\treturn err\n\t}\n\tvar dictionaries []system.SysDictionary\n\terr = global.GVA_DB.WithContext(ctx).Preload(\"SysDictionaryDetails\").Find(&dictionaries, \"id in (?)\", dictInfo.Dictionaries).Error\n\tif err != nil {\n\t\treturn err\n\t}\n\tdictExpr := ast.CreateDictionaryStructAst(dictionaries)\n\tarrayAst.Elts = *dictExpr\n\n\treturn writePluginInitializeFile(dictPath, fileSet, astFile)\n}\n\nfunc (s *autoCodePlugin) Remove(ctx context.Context, pluginName string, pluginType string) (err error) {\n\tif err = utils.ValidatePluginName(pluginName); err != nil {\n\t\treturn err\n\t}\n\tif pluginType != \"web\" && pluginType != \"server\" && pluginType != \"full\" {\n\t\treturn errors.New(\"invalid plugin type\")\n\t}\n\n\tvar webDir, serverDir string\n\tif pluginType == \"web\" || pluginType == \"full\" {\n\t\twebDir, err = pluginPath(global.GVA_CONFIG.AutoCode.Web, pluginName)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif pluginType == \"server\" || pluginType == \"full\" {\n\t\tserverDir, err = pluginPath(global.GVA_CONFIG.AutoCode.Server, pluginName)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// 1. 删除前端代码\n\tif pluginType == \"web\" || pluginType == \"full\" {","sourceCodeStart":884,"sourceCodeEnd":920,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_plugin.go#L884-L920","documentation":"autoCodePlugin.Remove deletes an installed plugin's files and deregisters its import. It only accepts pluginType values \"web\", \"server\", or \"full\"; any other string is rejected with \"invalid plugin type\" before any filesystem work happens.","triggerScenarios":"Calling Remove with pluginType not exactly one of \"web\"/\"server\"/\"full\" — e.g. \"frontend\", \"backend\", \"all\", empty string, or wrong casing (\"Web\").","commonSituations":"Frontend UI sending a translated or legacy type value; API consumers guessing the parameter; case-sensitivity mistakes when calling the service directly.","solutions":["Pass exactly \"web\", \"server\", or \"full\" (lowercase) as pluginType.","Map UI-side values to these three literals before invoking Remove.","Update stale API clients or documentation using older type names."],"exampleFix":"// before\ns.Remove(ctx, \"myplugin\", \"Frontend\")\n// after\ns.Remove(ctx, \"myplugin\", \"web\")","handlingStrategy":"validation","validationCode":"var allowed = map[string]bool{\"web\": true, \"server\": true, \"full\": true}\nif !allowed[pluginType] {\n    return fmt.Errorf(\"pluginType 必须是 web/server/full, 收到: %q\", pluginType)\n}\n// safe to call Remove","typeGuard":"func isValidPluginType(t string) bool {\n    return t == \"web\" || t == \"server\" || t == \"full\"\n}","tryCatchPattern":"if err := plugService.Remove(ctx, name, pluginType); err != nil {\n    if err.Error() == \"invalid plugin type\" {\n        return fmt.Errorf(\"仅支持 web/server/full: %w\", err)\n    }\n    return err\n}","preventionTips":["Constrain UI selects to the three literals web/server/full.","Normalize/lowercase user input before calling Remove.","Share a constant set between frontend and backend instead of free-form strings.","Add API-layer binding validation (oneof=web server full)."],"tags":["validation","plugin","api","params"],"backgroundTag":"invalid-parameter","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}