docker/cli · error

invalid credential spec: spec specifies config

Error message

invalid credential spec: spec specifies config %v, but no such config can be found

What it means

Returned by convertCredentialSpec when the spec names a config but none of the already-built ConfigReferences match it, even after namespacing (service.go:707-721). The credential spec needs the config's runtime ID, so the referenced config must be one the service actually mounts/uses.

Solutions

  1. Ensure the config named in credential_spec.config is also listed in the service's `configs:` block.
  2. Check spelling/casing of the config name in both places.
  3. If the config is external, declare and mount it so a ConfigReference exists to resolve the ID.

Example fix

// before
services:
  web:
    image: iis
    credential_spec:
      config: gmsa-cred
// after
services:
  web:
    image: iis
    credential_spec:
      config: gmsa-cred
    configs:
      - gmsa-cred
configs:
  gmsa-cred:
    external: true
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the config named by credential_spec.config is also mounted by the service.
func validateCredentialSpecConfig(cfg *composetypes.Config) error {
    for _, svc := range cfg.Services {
        name := svc.CredentialSpec.Config
        if name == "" {
            continue
        }
        found := false
        for _, c := range svc.Configs {
            if c.Source == name { found = true; break }
        }
        if !found {
            return fmt.Errorf("credential_spec config %q must be listed in the service configs", name)
        }
    }
    return nil
}

Prevention

When it happens

Trigger: Setting credential_spec.config to a name that is not in the service's configs list AND not resolvable via the namespace scope of any existing ConfigReference. Both the direct-name loop (service.go:708-713) and the namespaced loop (service.go:715-720) fail to find a match.

Common situations: credential_spec.config names a config that isn't declared under the service's `configs:`; typos; referencing a config by a name that only exists external but isn't mounted.

Related errors


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

Appendix: source

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

	}
	swarmCredSpec := swarm.CredentialSpec(spec)
	// if we're using a swarm Config for the credential spec, over-write it
	// here with the config ID
	if swarmCredSpec.Config != "" {
		for _, config := range refs {
			if swarmCredSpec.Config == config.ConfigName {
				swarmCredSpec.Config = config.ConfigID
				return &swarmCredSpec, nil
			}
		}
		// if none of the configs match, try namespacing
		for _, config := range refs {
			if namespace.Scope(swarmCredSpec.Config) == config.ConfigName {
				swarmCredSpec.Config = config.ConfigID
				return &swarmCredSpec, nil
			}
		}
		return nil, fmt.Errorf("invalid credential spec: spec specifies config %v, but no such config can be found", swarmCredSpec.Config)
	}
	return &swarmCredSpec, nil
}

func convertUlimits(origUlimits map[string]*composetypes.UlimitsConfig) []*container.Ulimit {
	ulimits := make([]*container.Ulimit, 0, len(origUlimits))
	for name, u := range origUlimits {
		soft, hard := int64(u.Soft), int64(u.Hard)
		if u.Single != 0 {
			soft, hard = int64(u.Single), int64(u.Single)
		}

		ulimits = append(ulimits, &container.Ulimit{
			Name: name,
			Soft: soft,
			Hard: hard,
		})
	}

View on GitHub (pinned to 4f84911bfe)