docker/cli · error
failed to cast to expected type
Error message
failed to cast to expected type: %w
What it means
Returned by recursiveInterpolate after a value was substituted but the path's registered caster failed to convert the resulting string to its target type (interpolation.go:69-71). The TypeCastMapping (e.g. toInt, toFloat, toBoolean) runs on fields like deploy.replicas or healthcheck.retries; a non-numeric/non-boolean interpolated value is rejected.
Solutions
- Set the environment variable to a valid value for the field's expected type (integer for replicas/ports, float for max_failure_ratio, yes/no/true/false/on/off for booleans).
- Provide a default in the template, e.g. ${REPLICAS:-2}, so an unset/empty var still casts.
- Check the unwrapped inner error (strconv.Atoi / ParseFloat / toBoolean) to see which value failed.
Example fix
# before
environment:
REPLICAS: auto
deploy:
replicas: ${REPLICAS}
# after
environment:
REPLICAS: "3"
deploy:
replicas: ${REPLICAS:-3} Defensive patterns
Strategy: validation
Validate before calling
// Validate interpolated values against their expected cast before handing the config to the loader.
var intPaths = []string{"deploy.replicas", "healthcheck.retries"}
func assertInt(name, val string) error {
if _, err := strconv.Atoi(val); err != nil {
return fmt.Errorf("%s must be an integer, got %q", name, val)
}
return nil
}
// if v := os.Getenv("REPLICAS"); v != "" { if err := assertInt("REPLICAS", v); err != nil { return err } } Prevention
- Provide defaults in templates (${VAR:-2}) so unset vars still cast.
- Ensure env vars for numeric/boolean fields hold valid values.
- Inspect the unwrapped inner error (strconv.Parse*) to see which value failed.
When it happens
Trigger: An interpolated compose value that must be int/float/bool ends up non-convertible after substitution, e.g. deploy.replicas: ${REPLICAS} with REPLICAS=auto, or healthcheck.retries set to a non-numeric env value. The caster error is wrapped at interpolation.go:71.
Common situations: Env var holding a typo or empty/non-numeric string; a variable reused across fields where the value is text; casting a boolean field to something other than yes/no/true/false/on/off.
Related errors
- error while interpolating
- invalid boolean
- invalid interpolation format for
- specify a Compose file (with --compose-file)
- cluster options are incompatible with type image
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/ab458ced7bd87826.
Report an issue: GitHub.
Appendix: source
Thrown at cli/compose/interpolation/interpolation.go:71
}
return out, nil
}
func recursiveInterpolate(value any, path Path, opts Options) (any, error) {
switch value := value.(type) {
case string:
newValue, err := opts.Substitute(value, template.Mapping(opts.LookupValue))
if err != nil || newValue == value {
return value, newPathError(path, err)
}
caster, ok := opts.getCasterForPath(path)
if !ok {
return newValue, nil
}
casted, err := caster(newValue)
if err != nil {
return casted, newPathError(path, fmt.Errorf("failed to cast to expected type: %w", err))
}
return casted, nil
case map[string]any:
out := map[string]any{}
for key, elem := range value {
interpolatedElem, err := recursiveInterpolate(elem, path.Next(key), opts)
if err != nil {
return nil, err
}
out[key] = interpolatedElem
}
return out, nil
case []any:
out := make([]any, len(value))
for i, elem := range value {
interpolatedElem, err := recursiveInterpolate(elem, path.Next(PathMatchList), opts)View on GitHub (pinned to 4f84911bfe)