docker/cli · error
invalid type %T for ulimits
Error message
invalid type %T for ulimits
What it means
Thrown by transformUlimits during schema transformation of a service's `ulimits` mapping. Each ulimit value must be either a bare integer (shorthand where soft==hard) or a map with `soft` and `hard` integer keys. Any other YAML scalar/sequence (quoted string, list, bool, null) hits the default branch and is rejected.
Solutions
- Use a bare integer: `ulimits: { nproc: 65535 }`.
- Or use the explicit map form: `ulimits: { nproc: { soft: 65535, hard: 65535 } }`.
- Remove any quotes around the numeric value.
Example fix
# before
services:
web:
ulimits:
nproc: "65535"
# after
services:
web:
ulimits:
nproc: 65535 Defensive patterns
Strategy: validation
Validate before calling
// validate service.ulimits before Transform()
func validateUlimits(svc map[string]any) error {
u, ok := svc["ulimits"]
if !ok {
return nil
}
m, ok := u.(map[string]any)
if !ok {
return fmt.Errorf("ulimits must be a mapping")
}
for name, v := range m {
switch t := v.(type) {
case int:
// ok
case map[string]any:
if _, ok := t["soft"].(int); !ok {
return fmt.Errorf("ulimits.%s.soft must be int", name)
}
if _, ok := t["hard"].(int); !ok {
return fmt.Errorf("ulimits.%s.hard must be int", name)
}
default:
return fmt.Errorf("ulimits.%s: invalid type %T", name, v)
}
}
return nil
} Type guard
func isUlimitValue(v any) bool {
switch v.(type) {
case int:
return true
case map[string]any:
_, softOk := v.(map[string]any)["soft"].(int)
_, hardOk := v.(map[string]any)["hard"].(int)
return softOk && hardOk
}
return false
} Prevention
- Run `docker compose config` to validate a file before deploying.
- Lint compose files in CI (e.g. docker compose config --quiet).
- Never quote numeric ulimit values.
When it happens
Trigger: A service defines `ulimits:` where an entry value is not int or map — e.g. `ulimits: nproc: "65535"` (quoted), `nproc: [65535]` (list), or `nproc: ~`. The transformer is invoked by Transform() for every key under service.ulimits.
Common situations: Quoting the number in YAML, copying an example whose indentation turns the map into a string, or tooling that emits ulimits as strings.
Related errors
- invalid type %T for map[string]string
- invalid type %T for port
- invalid type %T for secret
- invalid type %T for service build
- invalid type %T for service volume
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/c8d86c5326d5b563.
Report an issue: GitHub.
Appendix: source
Thrown at cli/compose/loader/loader.go:535
logrus.Warn("cannot expand '~', because the environment lacks HOME")
return srcPath
}
return strings.Replace(srcPath, "~", home, 1)
}
return srcPath
}
func transformUlimits(data any) (any, error) {
switch value := data.(type) {
case int:
return types.UlimitsConfig{Single: value}, nil
case map[string]any:
ulimit := types.UlimitsConfig{}
ulimit.Soft = value["soft"].(int)
ulimit.Hard = value["hard"].(int)
return ulimit, nil
default:
return data, fmt.Errorf("invalid type %T for ulimits", value)
}
}
// LoadNetworks produces a NetworkConfig map from a compose file Dict
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadNetworks(source map[string]any, version string) (map[string]types.NetworkConfig, error) {
networks := make(map[string]types.NetworkConfig)
err := Transform(source, &networks)
if err != nil {
return networks, err
}
for name, nw := range networks {
if !nw.External.External {
continue
}
switch {
case nw.External.Name != "":
if nw.Name != "" {View on GitHub (pinned to 4f84911bfe)