argoproj/argo-workflows · error

unable to convert object %s to configmap when syncing Config

Error message

unable to convert object %s to configmap when syncing ConfigMaps

What it means

GetConfigMapValue fetches a ConfigMap via the Kubernetes API and asserts the returned object is actually a *apiv1.ConfigMap. Since the List/Get was filtered by name this should always be a ConfigMap; failure indicates a client/typing mismatch (e.g. wrong scheme, mocked client, or object of another kind with the same name).

Source

Thrown at workflow/common/configmap.go:24

	apiv1 "k8s.io/api/core/v1"

	"github.com/argoproj/argo-workflows/v4/errors"
)

type ConfigMapStore interface {
	GetByKey(key string) (any, bool, error)
}

// GetConfigMapValue retrieves a configmap value
func GetConfigMapValue(configMapStore ConfigMapStore, namespace, name, key string) (string, error) {
	obj, exists, err := configMapStore.GetByKey(namespace + "/" + name)
	if err != nil {
		return "", err
	}
	if exists {
		cm, ok := obj.(*apiv1.ConfigMap)
		if !ok {
			return "", fmt.Errorf("unable to convert object %s to configmap when syncing ConfigMaps", name)
		}
		if cmType := cm.Labels[LabelKeyConfigMapType]; cmType != LabelValueTypeConfigMapParameter {
			return "", fmt.Errorf(
				"ConfigMap '%s' needs to have the label %s: %s to load parameters",
				name, LabelKeyConfigMapType, LabelValueTypeConfigMapParameter)
		}
		cmValue, ok := cm.Data[key]
		if !ok {
			return "", errors.Errorf(errors.CodeNotFound, "ConfigMap '%s' does not have the key '%s'", name, key)
		}
		return cmValue, nil
	}
	return "", errors.Errorf(errors.CodeNotFound, "ConfigMap '%s' does not exist. Please make sure it has the label %s: %s to be detectable by the controller",
		name, LabelKeyConfigMapType, LabelValueTypeConfigMapParameter)
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Verify the object with that name in that namespace is truly a ConfigMap (kubectl get cm <name> -n <ns>)
  2. If in tests, ensure the fake client only returns *apiv1.ConfigMap objects for GetConfigMapValue paths
  3. Recreate the object with 'kubectl create configmap' if it is some other kind
  4. Check client construction (scheme/RESTMapper) if using a custom or offline apiclient

Example fix

// before (test)
fakeClient.PrependReactor("get", "configmaps", func(...) { return &appsv1.Deployment{}, nil })
// after
fakeClient.PrependReactor("get", "configmaps", func(...) { return &corev1.ConfigMap{ObjectMeta: ...}, nil })
Defensive patterns

Strategy: type-guard

Validate before calling

obj, err := client.CoreV1().ConfigMaps(ns).Get(ctx, name, metav1.GetOptions{})
// typed Get already guarantees *apiv1.ConfigMap; avoid untyped dynamic client here

Type guard

func asConfigMap(obj runtime.Object) (*corev1.ConfigMap, bool) {
  cm, ok := obj.(*corev1.ConfigMap)
  return cm, ok
}

Try / catch

cm, err := GetConfigMapValue(...)
if err != nil && strings.Contains(err.Error(), "unable to convert object") {
  log.Printf("object %s is not a ConfigMap; check kind and client scheme", name)
}

Prevention

When it happens

Trigger: The k8s object returned by the client for the given name/namespace fails the *apiv1.ConfigMap type assertion — typically when using an offline/mocked client or a client configured against a nonstandard scheme.

Common situations: Unit tests injecting foreign objects into a fake clientset; CRD or other object shadowing the ConfigMap name; client-go scheme not registering corev1 properly in custom transports.

Related errors


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