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
- Ensure the config named in credential_spec.config is also listed in the service's `configs:` block.
- Check spelling/casing of the config name in both places.
- 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
- Always mount (via the service's configs:) any config referenced by credential_spec.config.
- Double-check spelling/casing of the config name in both places.
- For external configs, declare and mount them so a resolvable ConfigReference exists.
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
- invalid credential spec: cannot specify both
- invalid credential spec: cannot specify both
- undefined config
- service
- undefined network
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)