{"record":{"id":"72d1e8b6dba765f1","repo":"argoproj/argo-workflows","slug":"alreadyexists","errorCode":"AlreadyExists","errorMessage":"sync limit cannot be created as it already exists","messagePattern":"sync limit cannot be created as it already exists","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/sync/sync_cm.go","lineNumber":40,"sourceCode":"\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,\n\t\t\tNamespace: req.Namespace,\n\t\t\tKey:       req.Key,\n\t\t\tLimit:     req.Limit,\n\t\t\tType:      syncpkg.SyncConfigType_CONFIGMAP,\n\t\t}, false)\n\t}\n\n\tcm = &corev1.ConfigMap{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      req.CmName,\n\t\t\tNamespace: req.Namespace,\n\t\t},\n\t\tData: map[string]string{\n\t\t\treq.Key: fmt.Sprint(req.Limit),\n\t\t},","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/sync/sync_cm.go#L22-L58","documentation":"createSyncLimit refuses to create a sync limit when the target configmap already contains the requested key; existing limits must be updated instead. It fetches the configmap first and checks cm.Data[req.Key].","triggerScenarios":"CreateSyncLimit targeting a configmap/key that already holds a limit value; note Get errors other than NotFound fall through to update semantics, but an existing key short-circuits with AlreadyExists.","commonSituations":"Re-running a bootstrap script that creates limits, two operators provisioning the same semaphore key, retrying a create after a partial success.","solutions":["Call UpdateSyncLimit instead of CreateSyncLimit to change the existing key's value","Delete the key from the configmap (or use DeleteSyncLimit) before re-creating","Make provisioning idempotent: on AlreadyExists, fall back to update"],"exampleFix":"// before\n_, err := client.CreateSyncLimit(ctx, req)\n// after\n_, err := client.CreateSyncLimit(ctx, req)\nif st, ok := status.FromError(err); ok && st.Code() == codes.AlreadyExists {\n    _, err = client.UpdateSyncLimit(ctx, &syncpkg.UpdateSyncLimitRequest{CmName: req.CmName, Namespace: req.Namespace, Key: req.Key, Limit: req.Limit})\n}","handlingStrategy":"try-catch","validationCode":"cm, err := kube.CoreV1().ConfigMaps(ns).Get(ctx, name, metav1.GetOptions{})\nif err == nil {\n    if _, exists := cm.Data[key]; exists { /* use update instead of create */ }\n}","typeGuard":null,"tryCatchPattern":"_, err := client.CreateSyncLimit(ctx, req)\nif st, ok := status.FromError(err); ok && st.Code() == codes.AlreadyExists {\n    _, err = client.UpdateSyncLimit(ctx, toUpdateReq(req))\n}","preventionTips":["Make limit provisioning idempotent (create-or-update)","Check the configmap key before creating","Serialize provisioning scripts to avoid duplicate creators"],"tags":["grpc","sync-limit","configmap","conflict"],"backgroundTag":"resource-already-exists","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"}