docker/cli · error
empty string specified for links
Error message
empty string specified for links
What it means
Thrown by opts.ParseLink when the input string is empty. ParseLink parses Docker's legacy container-link format ("name:alias") used by --link; an empty string has no container name to resolve, so it is rejected outright. This guard sits at the very top of the function before any splitting occurs.
Solutions
- Omit the --link flag entirely when no link is needed.
- Ensure the link variable is non-empty before passing it: guard with a length/emptiness check.
- If building Links programmatically, filter out empty strings from the slice before submission.
Example fix
// before
name, alias, err := opts.ParseLink("")
// after
if l == "" {
return errors.New("link must not be empty")
}
name, alias, err := opts.ParseLink(l) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(link) == "" {
return fmt.Errorf("link must not be empty")
}
name, alias, err := opts.ParseLink(link) Try / catch
name, alias, err := opts.ParseLink(link)
if err != nil {
// log err; skip this link or abort
return err
} Prevention
- Filter empty strings out of any Links slice before submission.
- Guard shell variables with [ -n "$VAR" ] before passing to --link.
When it happens
Trigger: Calling opts.ParseLink(""), passing --link "" to docker run/create, or constructing a HostConfig.Links slice that contains an empty element.
Common situations: Shell scripting docker run with an unset/empty link variable, e.g. LINK=""; docker run --link "$LINK:alias". Also happens when programmatically building the Links slice from filtered or missing data.
Related errors
- bad format for links
- conflicting options: cannot specify both --link and…
- invalid restart policy format: no policy provided before…
- invalid restart policy format: maximum retry count must be…
- source is required
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/71319f042dc999f7.
Report an issue: GitHub.
Appendix: source
Thrown at opts/opts.go:374
}
// ParseCPUs takes a string ratio and returns an integer value of nano cpus
func ParseCPUs(value string) (int64, error) {
cpu, ok := new(big.Rat).SetString(value)
if !ok {
return 0, fmt.Errorf("failed to parse %v as a rational number", value)
}
nano := cpu.Mul(cpu, big.NewRat(1e9, 1))
if !nano.IsInt() {
return 0, errors.New("value is too precise")
}
return nano.Num().Int64(), nil
}
// ParseLink parses and validates the specified string as a link format (name:alias)
func ParseLink(val string) (string, string, error) {
if val == "" {
return "", "", errors.New("empty string specified for links")
}
// We expect two parts, but restrict to three to allow detecting invalid formats.
arr := strings.SplitN(val, ":", 3)
// TODO(thaJeztah): clean up this logic!!
if len(arr) > 2 {
return "", "", errors.New("bad format for links: " + val)
}
// TODO(thaJeztah): this should trim the "/" prefix as well??
if len(arr) == 1 {
return val, val, nil
}
// This is kept because we can actually get a HostConfig with links
// from an already created container and the format is not `foo:bar`
// but `/foo:/c1/bar`
if strings.HasPrefix(arr[0], "/") {
// TODO(thaJeztah): clean up this logic!!
_, alias := path.Split(arr[1])View on GitHub (pinned to 4f84911bfe)