docker/cli · error

context name is invalid, names are validated against regexp

Error message

context name %q is invalid, names are validated against regexp %q

What it means

Returned by ValidateContextName (used during context create/import) when the name fails `^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$`: it must start with an alphanumeric character, be at least 2 characters, and contain only alphanumerics plus `_ . + -`. Empty names and the reserved name 'default' are also rejected (with their own messages).

Solutions

  1. Choose a name starting with a letter/digit, 2+ characters, containing only `[a-zA-Z0-9_.+-]`.
  2. Avoid 'default' and characters like space, slash, colon, @, and any non-ASCII rune.
  3. Validate the name with the same regex before calling the API.

Example fix

// before
if err := store.ValidateContextName(name); err != nil { ... }
// name = "my context" -> rejected

// after: sanitize before validating
name = regexp.MustCompile(`[^a-zA-Z0-9_.+-]`).ReplaceAllString(name, "-")
if err := store.ValidateContextName(name); err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

var contextNameRE = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$`)

func validContextName(name string) bool {
    return name != "" && name != "default" && contextNameRE.MatchString(name)
}

if !validContextName(name) {
    return fmt.Errorf("invalid context name %q", name)
}

Prevention

When it happens

Trigger: Calling `docker context create`/import with a name such as 'my context' (space), 'a' (too short, <2 chars), '-foo' (leading separator), 'my@ctx' (@ not allowed), 'café' (non-ASCII), or 'default' (reserved).

Common situations: Names generated from CI variables containing spaces or slashes; leading dash/number sign; reserved 'default'; Unicode names; names with colons or @.

Related errors


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

Appendix: source

Thrown at cli/context/store/store.go:224

// GetStorageInfo returns the paths where the Metadata and TLS data are stored
// for the context.
func (s *ContextStore) GetStorageInfo(contextName string) StorageInfo {
	return StorageInfo{
		MetadataPath: s.meta.contextDir(contextdirOf(contextName)),
		TLSPath:      s.tls.contextDir(contextName),
	}
}

// ValidateContextName checks a context name is valid.
func ValidateContextName(name string) error {
	if name == "" {
		return errors.New("context name cannot be empty")
	}
	if name == "default" {
		return errors.New(`"default" is a reserved context name`)
	}
	if !isValidName(name) {
		return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, validNameFormat)
	}
	return nil
}

// validNameFormat is used as part of errors for invalid context-names.
// We should consider making this less technical ("must start with "a-z",
// and only consist of alphanumeric characters and separators").
const validNameFormat = `^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$`

// isValidName checks if the context-name is valid ("^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$").
//
// Names must start with an alphanumeric character (a-zA-Z0-9), followed by
// alphanumeric or separators ("_", ".", "+", "-").
func isValidName(s string) bool {
	if len(s) < 2 || !isAlphaNum(s[0]) {
		return false
	}

View on GitHub (pinned to 4f84911bfe)