{"record":{"id":"ab61333d0a8aac0b","repo":"argoproj/argo-workflows","slug":"invalidargument-ab6133","errorCode":"InvalidArgument","errorMessage":"limit must be greater than zero","messagePattern":"limit must be greater than zero","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/sync/sync_cm.go","lineNumber":25,"sourceCode":"\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang.org/grpc/status\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\tsyncpkg \"github.com/argoproj/argo-workflows/v4/pkg/apiclient/sync\"\n\t\"github.com/argoproj/argo-workflows/v4/server/auth\"\n\tsutils \"github.com/argoproj/argo-workflows/v4/server/utils\"\n\tauthutil \"github.com/argoproj/argo-workflows/v4/util/auth\"\n)\n\ntype configMapSyncProvider struct{}\n\nvar _ ConfigProvider = &configMapSyncProvider{}\n\nfunc (s *configMapSyncProvider) createSyncLimit(ctx context.Context, req *syncpkg.CreateSyncLimitRequest) (*syncpkg.SyncLimitResponse, error) {\n\tif req.Limit <= 0 {\n\t\treturn nil, sutils.ToStatusError(fmt.Errorf(\"limit must be greater than zero\"), codes.InvalidArgument)\n\t}\n\n\tif err := checkConfigMapPermission(ctx, \"create\", req.Namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tkubeClient := auth.GetKubeClient(ctx)\n\n\tconfigmapGetter := kubeClient.CoreV1().ConfigMaps(req.Namespace)\n\n\tcm, err := configmapGetter.Get(ctx, req.CmName, metav1.GetOptions{})\n\tif err == nil {\n\t\t_, has := cm.Data[req.Key]\n\t\tif has {\n\t\t\treturn nil, sutils.ToStatusError(fmt.Errorf(\"sync limit cannot be created as it already exists\"), codes.AlreadyExists)\n\t\t}\n\t\treturn s.handleUpdateSyncLimit(ctx, &syncpkg.UpdateSyncLimitRequest{\n\t\t\tCmName:    req.CmName,","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/sync/sync_cm.go#L7-L43","documentation":"The configmap-backed sync-limit gRPC API rejects CreateSyncLimit requests whose Limit field is zero or negative. Limits model semaphore slot counts and must be positive integers. The check runs before permission and configmap access.","triggerScenarios":"Calling the SyncService.CreateSyncLimit gRPC/CLI with limit: 0 or a negative value in the CreateSyncLimitRequest.","commonSituations":"Default-zero protobuf int32 left unset by clients, UI sending 0 for 'unset', or computed limits evaluating to 0.","solutions":["Pass a positive integer limit (>= 1) in the request","Check the calling client/UI is not sending the zero-value default","Use UpdateSyncLimit/DeleteSyncLimit semantics intentionally rather than limit 0"],"exampleFix":"// before\nreq := &syncpkg.CreateSyncLimitRequest{CmName: \"my-cm\", Key: \"k\", Limit: 0}\n// after\nreq := &syncpkg.CreateSyncLimitRequest{CmName: \"my-cm\", Key: \"k\", Limit: 3}","handlingStrategy":"validation","validationCode":"if limit < 1 { return fmt.Errorf(\"CreateSyncLimit requires limit >= 1, got %d\", limit) }","typeGuard":"func validLimit(n int32) bool { return n > 0 }","tryCatchPattern":"_, err := syncClient.CreateSyncLimit(ctx, req)\nif st, ok := status.FromError(err); ok && st.Code() == codes.InvalidArgument {\n    return fmt.Errorf(\"bad request: %v\", st.Message())\n}","preventionTips":["Never rely on protobuf zero-value ints for required fields","Clamp computed semaphore sizes to a minimum of 1","Validate limit input in CLIs/UIs before calling the API"],"tags":["grpc","sync-limit","validation","configmap"],"backgroundTag":"invalid-parameter","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}