docker/cli · error · invalidParameterErr
invalid detach keys ( )
Error message
invalid detach keys (%s): %w
What it means
Returned by validateDetachKeys (hijack.go:38) when term.ToBytes cannot parse the --detach-keys value. Detach keys are converted to a byte sequence; an unparseable specifier (e.g. an unknown key name) produces this error, wrapped by invalidParameter so it is treated as a client-side usage error.
Solutions
- Use the documented format, e.g. --detach-keys=ctrl-p,ctrl-x or a single key like --detach-keys=q.
- Check ~/.docker/config.json detachKeys if set globally.
- Remove the flag to use the default (ctrl-p ctrl-q).
Example fix
# before docker attach --detach-keys=ctrl+p&ctrl+x box # after docker attach --detach-keys=ctrl-p,ctrl-x box
Defensive patterns
Strategy: validation
Validate before calling
// Validate detach-keys syntax the same way the CLI does:
import "github.com/moby/term"
if _, err := term.ToBytes(detachKeys); err != nil {
return fmt.Errorf("bad --detach-keys %q: %w", detachKeys, err)
} Try / catch
if err != nil && strings.Contains(err.Error(), "invalid detach keys") {
// fall back to the default ctrl-p,ctrl-q by dropping the flag
} Prevention
- Prefer documented tokens like ctrl-p,ctrl-x.
- Omit --detach-keys to use the default.
- Validate the value before scripting it into many commands.
When it happens
Trigger: Passing `--detach-keys` with a value term.ToBytes cannot understand: an unrecognized token, malformed escape, or a sequence with trailing garbage. Common in `docker attach`, `docker exec`, `docker run -it`.
Common situations: Typo in a key name (e.g. ctrl-p&ctrl-x mistyped), copy-paste of an unsupported sequence, or a config-file detachKeys value from an older/incompatible Docker version.
Related errors
- unable to setup input stream
- invalid pull option: ' ': must be one of , or
- unable to set IO streams as raw terminal
- failed to parse template
- cowardly refusing to export to a terminal, specify a file…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/6fbc57c4b87bc528.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/hijack.go:38
// readCloserWrapper wraps an io.Reader, and implements an io.ReadCloser
// It calls the given callback function when closed.
type readCloserWrapper struct {
io.Reader
closer func() error
}
// Close calls back the passed closer function
func (r *readCloserWrapper) Close() error {
return r.closer()
}
func validateDetachKeys(keys string) error {
if keys == "" {
return nil
}
if _, err := term.ToBytes(keys); err != nil {
return invalidParameter(fmt.Errorf("invalid detach keys (%s): %w", keys, err))
}
return nil
}
// A hijackedIOStreamer handles copying input to and output from streams to the
// connection.
type hijackedIOStreamer struct {
streams command.Streams
inputStream io.ReadCloser
outputStream io.Writer
errorStream io.Writer
resp client.HijackedResponse
tty bool
detachKeys string
}
View on GitHub (pinned to 4f84911bfe)