argoproj/argo-workflows · error

if you have an item in your config map named 'config', you m

Error message

if you have an item in your config map named 'config', you must only have one item

What it means

parseConfigMap reads the workflow-controller-configmap. If a key literally named `config` exists, it must be the ONLY key, since `config` holds the entire YAML document while other keys are treated as individual top-level entries. Mixed usage is ambiguous, so it is rejected with this error.

Source

Thrown at config/controller.go:43

	// name of the config map
	configMap     string
	kubeclientset kubernetes.Interface
}

func NewController(namespace, name string, kubeclientset kubernetes.Interface) Controller {
	return &controller{
		namespace:     namespace,
		configMap:     name,
		kubeclientset: kubeclientset,
	}
}

func parseConfigMap(cm *apiv1.ConfigMap, config *Config) error {
	// The key in the configmap to retrieve workflow configuration from.
	// Content encoding is expected to be YAML.
	rawConfig, ok := cm.Data["config"]
	if ok && len(cm.Data) != 1 {
		return fmt.Errorf("if you have an item in your config map named 'config', you must only have one item")
	}
	if !ok {
		for name, value := range cm.Data {
			if strings.Contains(value, "\n") {
				// this mucky code indents with two spaces
				rawConfig = rawConfig + name + ":\n  " + strings.Join(strings.Split(strings.Trim(value, "\n"), "\n"), "\n  ") + "\n"
			} else {
				rawConfig = rawConfig + name + ": " + value + "\n"
			}
		}
	}
	err := yaml.UnmarshalStrict([]byte(rawConfig), config)
	return err
}

func (cc *controller) Get(ctx context.Context) (*Config, error) {
	cmClient := cc.kubeclientset.CoreV1().ConfigMaps(cc.namespace)
	cm, err := cmClient.Get(ctx, cc.configMap, metav1.GetOptions{})

View on GitHub (pinned to 35bff19146)

Solutions

  1. Merge all configuration into the single `config` YAML key and delete the other keys from the configmap.
  2. Alternatively migrate fully to per-key entries (the non-`config` style) and remove the `config` key.
  3. Apply the corrected configmap with kubectl and let the controller reload it.
  4. Audit chart/tooling that writes extra keys into workflow-controller-configmap and pin them to one of the two accepted formats.

Example fix

// before
data:
  config: |
    containerRuntimeExecutor: emissary
  links: |
    ...
// after
data:
  config: |
    containerRuntimeExecutor: emissary
    links:
      - ...
Defensive patterns

Strategy: validation

Validate before calling

// validate configmap keys before apply
keys := listConfigMapKeys("workflow-controller-configmap")
if containsKey(keys, "config") && len(keys) > 1 {
    return errors.New("key 'config' must be the only key in the configmap")
}

Type guard

func isLegacySingleKeyConfig(cm *apiv1.ConfigMap) bool {
    _, ok := cm.Data["config"]
    return ok && len(cm.Data) == 1
}

Try / catch

cfg, err := config.Parse(ctx, cm)
if err != nil {
    return nil, fmt.Errorf("invalid workflow-controller-configmap (merge everything into one 'config' key or all separate keys): %w", err)
}

Prevention

When it happens

Trigger: The configmap contains a `config` key plus at least one other key (len(cm.Data) != 1) when Parse/parseConfigMap runs, e.g. during controller startup or config reload.

Common situations: Operators adding a new setting as a separate key while the legacy single `config` YAML key is still present; leftover keys from Helm charts or tooling writing extra entries (tls, secrets-style keys) into the same configmap.

Related errors


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