Description
In the #2677 a choice was made to return 0 in case container doesn't exist.
Good intention, terrible execution, 0 exit code is returned but error is printed to console
docker rm -f nonexistent
Error response from daemon: No such container: nonexistent
Why this is bad
-
It Breaks Log Parsing: If one writes an automated monitoring agent (like Datadog or a simple log scraper) to watch server logs for the string "Error response from daemon", it will trigger a false-positive alert every time a clean, successful container purge script runs.
-
It Destroys Trust in set -e: Developers use set -e specifically so they don't have to manually write error checking after every single line of code. By making a command print a blatant error but return a success code, Docker actively gaslights the shell environment.
-
It Introduces Deception: it forces developers to write wildly over-engineered safety guards (like parsing docker inspect --type=container) just to protect their scripts from Docker’s internal exit-code lying.
If a tool prints the word "Error", it should emit an error code. If it returns "Success", it should shut up. Docker trying to do both at the same time is bad API design, plain and simple.
Reproduce
docker rm -f nonexistent
echo "DEBUG: 'docker rm' exited with code: $?"
Result:
Error response from daemon: No such container: nonexistent
DEBUG: 'docker rm' exited with code: 0
Expected behavior
On 0 return code no error message should be produced
docker version
Client:
Version: 29.4.0-ce
API version: 1.54
Go version: go1.26.3
Git commit: daa0cb7f23
Built: Wed May 6 04:59:34 2026
OS/Arch: linux/amd64
Context: default
Server:
Engine:
Version: 29.4.0-ce
API version: 1.54 (minimum version 1.40)
Go version: go1.26.3
Git commit: daa0cb7f23
Built: Wed May 6 04:59:34 2026
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.7.29
GitCommit: 442cb34bda9a6a0fed82a2ca7cade05c5c749582
runc:
Version: 1.4.1
GitCommit: v1.4.1-0-gc67132530367
docker-init:
Version: 0.2.1_catatonit
GitCommit:
docker info
Client:
Version: 29.4.0-ce
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: 0.33.0
Path: /usr/lib/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: 5.1.4
Path: /usr/lib/docker/cli-plugins/docker-compose
Server:
Containers: 6
Running: 5
Paused: 0
Stopped: 1
Images: 30
Server Version: 29.4.0-ce
Storage Driver: overlayfs
driver-type: io.containerd.snapshotter.v1
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
CDI spec directories:
/etc/cdi
/var/run/cdi
Swarm: active
NodeID: kmynlms2gqysq120xhxbqe6sl
Is Manager: true
ClusterID: 01w7otx4wv6p9ycpn9t9b76q0
Managers: 1
Nodes: 1
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
Data Path Port: 4789
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 10
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 192.168.0.111
Manager Addresses:
192.168.0.111:2377
Runtimes: io.containerd.runc.v2 oci runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 442cb34bda9a6a0fed82a2ca7cade05c5c749582
runc version: v1.4.1-0-gc67132530367
init version:
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 7.0.12-1-default
Operating System: openSUSE Tumbleweed
OSType: linux
Architecture: x86_64
CPUs: 32
Total Memory: 62.51GiB
Name: localhost.localdomain
ID: 5d0600ed-7c12-4f09-84f7-158a0ef492fc
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
::1/128
127.0.0.0/8
Live Restore Enabled: false
Firewall Backend: iptables+firewalld
Additional Info
No response
Description
In the #2677 a choice was made to return 0 in case container doesn't exist.
Good intention, terrible execution, 0 exit code is returned but error is printed to console
Why this is bad
It Breaks Log Parsing: If one writes an automated monitoring agent (like Datadog or a simple log scraper) to watch server logs for the string "Error response from daemon", it will trigger a false-positive alert every time a clean, successful container purge script runs.
It Destroys Trust in set -e: Developers use set -e specifically so they don't have to manually write error checking after every single line of code. By making a command print a blatant error but return a success code, Docker actively gaslights the shell environment.
It Introduces Deception: it forces developers to write wildly over-engineered safety guards (like parsing docker inspect --type=container) just to protect their scripts from Docker’s internal exit-code lying.
If a tool prints the word "Error", it should emit an error code. If it returns "Success", it should shut up. Docker trying to do both at the same time is bad API design, plain and simple.
Reproduce
docker rm -f nonexistent
echo "DEBUG: 'docker rm' exited with code: $?"
Result:
Error response from daemon: No such container: nonexistent
DEBUG: 'docker rm' exited with code: 0
Expected behavior
On 0 return code no error message should be produced
docker version
Client: Version: 29.4.0-ce API version: 1.54 Go version: go1.26.3 Git commit: daa0cb7f23 Built: Wed May 6 04:59:34 2026 OS/Arch: linux/amd64 Context: default Server: Engine: Version: 29.4.0-ce API version: 1.54 (minimum version 1.40) Go version: go1.26.3 Git commit: daa0cb7f23 Built: Wed May 6 04:59:34 2026 OS/Arch: linux/amd64 Experimental: false containerd: Version: v1.7.29 GitCommit: 442cb34bda9a6a0fed82a2ca7cade05c5c749582 runc: Version: 1.4.1 GitCommit: v1.4.1-0-gc67132530367 docker-init: Version: 0.2.1_catatonit GitCommit:docker info
Additional Info
No response