docker/cli · error

undefined config

Error message

undefined config %q

What it means

Returned by the config lookup closure inside convertServiceConfigObjs when a config referenced by a service is absent from the top-level configSpecs map (service.go:300-303). Compose configs (Swarm configs) must be declared before use.

Solutions

  1. Add the config under the top-level `configs:` key (file-backed or external).
  2. If it already exists in Swarm, declare it `external: true` with its real name.
  3. Fix the service's config name to match an existing declaration.

Example fix

// before
services:
  web:
    image: nginx
    configs:
      - site.conf
// after
services:
  web:
    image: nginx
    configs:
      - site.conf
configs:
  site.conf:
    file: ./site.conf
Defensive patterns

Strategy: validation

Validate before calling

func validateConfigsDeclared(cfg *composetypes.Config) error {
    for _, svc := range cfg.Services {
        for _, c := range svc.Configs {
            if _, ok := cfg.Configs[c.Source]; !ok {
                return fmt.Errorf("undefined config %q", c.Source)
            }
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A service's `configs:` list references a config not declared in the top-level `configs:` block; the lookup at service.go:301 returns false.

Common situations: Config mounted into a service but never declared; renamed a config in only one location; intended to use an external Swarm config but forgot `external: true`.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/f3ff3445433d0837. Report an issue: GitHub.

Appendix: source

Thrown at cli/compose/convert/service.go:302

// and a set of compose Config specs, and creates the swarm ConfigReferences
// required by the service. Unlike convertServiceSecrets, this takes the whole
// ServiceConfig, because some Configs may be needed as a result of other
// fields (like CredentialSpecs).
//
// TODO: fix configs API so that ConfigsAPIClient is not required here
func convertServiceConfigObjs(
	ctx context.Context,
	apiClient client.ConfigAPIClient,
	namespace Namespace,
	service composetypes.ServiceConfig,
	configSpecs map[string]composetypes.ConfigObjConfig,
) ([]*swarm.ConfigReference, error) {
	refs := []*swarm.ConfigReference{}

	lookup := func(key string) (composetypes.FileObjectConfig, error) {
		configSpec, exists := configSpecs[key]
		if !exists {
			return composetypes.FileObjectConfig{}, fmt.Errorf("undefined config %q", key)
		}
		return composetypes.FileObjectConfig(configSpec), nil
	}
	for _, config := range service.Configs {
		obj, err := convertFileObject(namespace, composetypes.FileReferenceConfig(config), lookup)
		if err != nil {
			return nil, err
		}

		file := swarm.ConfigReferenceFileTarget(obj.File)
		refs = append(refs, &swarm.ConfigReference{
			File:       &file,
			ConfigName: obj.Name,
		})
	}

	// finally, after converting all file objects, create any
	// Runtime-type configs that are needed. these are configs that are not

View on GitHub (pinned to 4f84911bfe)