WithStartupCommand silently swallows non-zero exit codes from the inner command
@locker95 đang làm issue này rồi.
Từ ngày 28/10/2026.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 76/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- docker, go
- Lĩnh vực
- backend-api-design, devtools
Hướng nghiên cứu
Bắt đầu trong container/options.go tại createExecutableHooks, sau đó kiểm tra Container.Exec trong container/container.exec.go để xác nhận cách mã thoát và lỗi được trả về. Thay đổi được hoàn tất khi các mã khác không từ WithStartupCommand và WithAfterReadyCommand được báo cáo là lỗi, trong khi các mã không và lỗi thực thi vẫn giữ nguyên hành vi như mong đợi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
container.WithStartupCommand registers a PostStarts lifecycle hook that runs each Executable via Container.Exec. When the inner command exits non-zero, the hook returns nil and container.Run reports success. The container ends up in a "running but the startup command failed" state with no visible signal to the caller.
Where
-
The hook is built in
container/options.go(createExecutableHooks):execFn := func(ctx context.Context, c ContainerInfo) error { if executor, ok := c.(ContainerExecutor); ok { _, _, err := executor.Exec(ctx, exec.AsCommand(), exec.Options()...) return err } return errors.New("container does not support execution") } -
Container.Execincontainer/container.exec.goreturns(int, io.Reader, error). The first return is the inner process's exit code — a value, not an error. The hook discards it.
Reproduction
c, err := container.Run(ctx,
container.WithImage("alpine:latest"),
container.WithEntrypoint("tail", "-f", "/dev/null"),
container.WithStartupCommand(exec.NewRawCommand([]string{"false"})),
)
// err == nil; c is up; the failing startup command is invisible.
This bites consumers in two ways:
- First-create coverage doesn't fail loudly. A startup command that errors is silently ignored at create time. The caller has no way to discover the failure short of checking side effects.
- The same trap applies to
WithAfterReadyCommand(same hook factory).
I hit this while writing tests for WithDurableStartupCommand (#154): a WithUser("nonexistent") case where su aborts, the rendered dispatcher exits non-zero, but Run still succeeds. I had to invoke the dispatcher directly via c.Exec and check the exit code value to observe the failure.
Suggested fix
Have createExecutableHooks (or a thin helper) treat a non-zero exit code as an error:
execFn := func(ctx context.Context, c ContainerInfo) error {
executor, ok := c.(ContainerExecutor)
if !ok {
return errors.New("container does not support execution")
}
code, _, err := executor.Exec(ctx, exec.AsCommand(), exec.Options()...)
if err != nil {
return err
}
if code != 0 {
return fmt.Errorf("startup command %v exited with code %d", exec.AsCommand(), code)
}
return nil
}
This is a behavioural change for any caller that today relies on startup-command failures being invisible — but I'd expect that population to be small, and the silent-failure mode is more dangerous than the loud one.
If a strictly backwards-compatible variant is preferred, an opt-in option (WithStrictStartupCommand?) could keep the current behaviour as the default.
Out of scope (but related)
Container.Exec's signature returning(int, io.Reader, error)makes the exit code easy to ignore. A future API revision could fold non-zero into theerrorreturn; for now, fixing the hook is the smaller change.
- Ngôn ngữ chính
- Go
- Star
- 133
- Fork
- 28
- Merge trung bình
- 3 giờ 55 phút
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của docker/go-sdk
-
Add Inspect method to the volume moduleCó thể đã có người làm @xHozey đã nhận 3 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
-
Proposal: Consider storing container name in Container structCó thể đã có người làm @xHozey đã nhận 266 ngày trước. Đang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
-
enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
-
chore
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
-
Train a small specialized modelĐang mởchore
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 10/100
Tất cả issue của docker/go-sdk
Issue tương tự
-
area/docs framework/hugo help wanted language/markdown
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 1 ngày
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:other issue-rating: 🦞 diamond lobster no-stale P2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
openclaw/crabbox#3060 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
kubeflow/semantic-operator#52 ·
Maintainer thường phản hồi trong vòng 10 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
PramodBasavarajMenasi/siftwise#52 ·
Maintainer thường phản hồi trong vòng 1 ngày