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
- Create the key in the configmap (via CreateSyncLimit or kubectl edit) before getting it
- Verify the key name spelling and namespace in the request
- 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
- Confirm key names against the workflow semaphore config before lookup
- Create limits as part of namespace bootstrap
- Use consistent naming constants for limit keys
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.