argoproj/argo-workflows · error

NotFound

NotFound

Error message

key %s not found in configmap %s/%s

What it means

GetSyncLimit reads the limit value from the configmap and errors with NotFound when the requested key is absent from cm.Data. This distinguishes 'configmap exists but key missing' from other failures.

Source

Thrown at server/sync/sync_cm.go:91

}

func (s *configMapSyncProvider) getSyncLimit(ctx context.Context, req *syncpkg.GetSyncLimitRequest) (*syncpkg.SyncLimitResponse, error) {
	if err := checkConfigMapPermission(ctx, "get", req.Namespace); err != nil {
		return nil, err
	}

	kubeClient := auth.GetKubeClient(ctx)

	configmapGetter := kubeClient.CoreV1().ConfigMaps(req.Namespace)

	cm, err := configmapGetter.Get(ctx, req.CmName, metav1.GetOptions{})
	if err != nil {
		return nil, sutils.ToStatusError(err, codes.Internal)
	}

	limit, ok := cm.Data[req.Key]
	if !ok {
		return nil, sutils.ToStatusError(fmt.Errorf("key %s not found in configmap %s/%s", req.Key, cm.Namespace, cm.Name), codes.NotFound)
	}

	parsedLimit, err := strconv.Atoi(limit)
	if err != nil {
		return nil, sutils.ToStatusError(fmt.Errorf("invalid limit format for key %s in configmap %s/%s", req.Key, cm.Namespace, cm.Name), codes.InvalidArgument)
	}

	return &syncpkg.SyncLimitResponse{
		CmName:    cm.Name,
		Namespace: cm.Namespace,
		Key:       req.Key,
		Limit:     int32(parsedLimit),
		Type:      syncpkg.SyncConfigType_CONFIGMAP,
	}, nil
}

func (s *configMapSyncProvider) updateSyncLimit(ctx context.Context, req *syncpkg.UpdateSyncLimitRequest) (*syncpkg.SyncLimitResponse, error) {
	if req.Limit <= 0 {

View on GitHub (pinned to 35bff19146)

Solutions

  1. Create the key in the configmap (via CreateSyncLimit or kubectl edit) before getting it
  2. Verify the key name spelling and namespace in the request
  3. List the configmap data (kubectl get cm <name> -o yaml) to confirm which keys exist

Example fix

// before
kubectl get cm my-cm -n ns  # key 'parallelism' missing
// after
kubectl create cm my-cm -n ns --from-literal=parallelism=5
Defensive patterns

Strategy: try-catch

Validate before calling

cm, _ := kube.CoreV1().ConfigMaps(ns).Get(ctx, name, metav1.GetOptions{})
if cm != nil { if _, ok := cm.Data[key]; !ok { return fmt.Errorf("key %s missing", key) } }

Try / catch

_, err := client.GetSyncLimit(ctx, req)
if st, ok := status.FromError(err); ok && st.Code() == codes.NotFound {
    // provision then retry: client.CreateSyncLimit(...)
}

Prevention

When it happens

Trigger: GetSyncLimit with a Key that was never written to the configmap, or after the key was deleted/renamed while the configmap itself still exists.

Common situations: Typo in the key name, configmap shared by multiple limits where only some keys exist, workflow semaphore config referencing a key the operator never created.

Understand the failure class

Background: "Not Found" / HTTP 404 Errors: What They Mean and How to Fix Them Across Libraries — this error's family across 6 libraries.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/30e124679cb550cb. Report an issue: GitHub.