{"record":{"id":"d4ba1b6715d87261","repo":"flipped-aurora/gin-vue-admin","slug":"api-d4ba1b","errorCode":null,"errorMessage":"存在无效API","messagePattern":"存在无效API","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/plugin/ai/service/sys_cli.go","lineNumber":298,"sourceCode":"\tif excludeID > 0 {\n\t\tquery = query.Where(\"id <> ?\", excludeID)\n\t}\n\tif err := query.First(&existing).Error; err != nil {\n\t\tif errors.Is(err, gorm.ErrRecordNotFound) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, err\n\t}\n\treturn true, nil\n}\n\nfunc (s *cliService) ensureApisExist(ctx context.Context, apiIDs []uint) error {\n\tvar count int64\n\tif err := global.GVA_DB.WithContext(ctx).Model(&sysModel.SysApi{}).Where(\"id IN ?\", apiIDs).Count(&count).Error; err != nil {\n\t\treturn err\n\t}\n\tif count != int64(len(apiIDs)) {\n\t\treturn errors.New(\"存在无效API\")\n\t}\n\treturn nil\n}\n\nfunc (s *cliService) listCliBindings(ctx context.Context, cliID uint) ([]sysCliManifestBinding, error) {\n\tvar bindings []autoModel.SysCliApi\n\tif err := global.GVA_DB.WithContext(ctx).Where(\"cli_id = ?\", cliID).Order(\"sort ASC, id ASC, api_id ASC\").Find(&bindings).Error; err != nil {\n\t\treturn nil, err\n\t}\n\tif len(bindings) == 0 {\n\t\treturn []sysCliManifestBinding{}, nil\n\t}\n\tapiIDs := make([]uint, 0, len(bindings))\n\tfor _, binding := range bindings {\n\t\tapiIDs = append(apiIDs, binding.ApiID)\n\t}\n\tvar apis []sysModel.SysApi\n\tif err := global.GVA_DB.WithContext(ctx).Where(\"id IN ?\", apiIDs).Find(&apis).Error; err != nil {","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/plugin/ai/service/sys_cli.go#L280-L316","documentation":"ensureApisExist counts SysApi rows matching the supplied apiIDs and requires an exact match with the number of (deduplicated) ids; any id that does not correspond to an existing sys_api row causes this error. It protects CLI-API bindings from referencing deleted or never-existing APIs.","triggerScenarios":"Calling AddCliApis with at least one ApiID that has no matching row in sys_api — e.g. an API deleted by another user, an id from a different environment's database, or a fabricated id in a hand-built request.","commonSituations":"Frontend kept a stale API list and the referenced API was deleted meanwhile; copying ids between dev/staging databases; importing binding configs exported from another instance; ids referencing plugin-provided APIs that are not installed.","solutions":["Verify every ApiID exists (SELECT id FROM sys_api WHERE id IN (...)) before binding","Reload the API list from the server so the UI offers only existing APIs","Remove the stale ids from the bindings payload","Re-sync environments so both sides share the same sys_api rows"],"exampleFix":"// before\napiIDs := []uint{1, 2, 999} // 999 deleted\ncliService.AddCliApis(ctx, reqWith(apiIDs))\n// after\nvar count int64\ndb.Model(&sysModel.SysApi{}).Where(\"id IN ?\", apiIDs).Count(&count)\nif count != int64(len(apiIDs)) { return errors.New(\"some APIs no longer exist\") }\ncliService.AddCliApis(ctx, reqWith(apiIDs))","handlingStrategy":"validation","validationCode":"var count int64\nglobal.GVA_DB.Model(&sysModel.SysApi{}).Where(\"id IN ?\", apiIDs).Count(&count)\nif count != int64(len(apiIDs)) {\n    return errors.New(\"some apiIds reference non-existent APIs\")\n}","typeGuard":null,"tryCatchPattern":"err := cliService.AddCliApis(ctx, req)\nif err != nil {\n    if err.Error() == \"存在无效API\" {\n        return fmt.Errorf(\"one or more APIs were deleted or do not exist; refresh the API list\")\n    }\n    return err\n}","preventionTips":["Refresh the API picker from the server before each binding operation","Remove ids of APIs deleted elsewhere instead of reusing cached lists","Do not copy ids across environments/databases","Run a periodic integrity check for sys_cli_api rows pointing at missing APIs"],"tags":["validation","referential-integrity","go","plugin-ai"],"backgroundTag":"referenced-entity-not-found","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}