From c373c618dd6a9fde057e109410115853705dcef5 Mon Sep 17 00:00:00 2001 From: Mohammed Olabie Date: Mon, 11 May 2026 18:33:45 +0300 Subject: [PATCH] cmd/docker: print command error before running plugin hooks Plugin hook output (such as Gordon's "What's next:" hint) was rendered before the command's own error message because hooks were invoked inside runDocker while the error was only printed in main() after runDocker returned. Print the error to stderr before invoking the hooks, and replace the error with a status-only StatusError so main() does not print the same message a second time. The original error message is captured up-front and still passed to the plugin hooks. Closes #6973 Signed-off-by: Mohammed Olabie --- cmd/docker/docker.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 0efcc70118fe..ccd522f6d781 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -543,10 +543,24 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error { cmd.SetArgs(args) err = cmd.ExecuteContext(ctx) + // Capture the error message before we may consume the error below; + // plugin hooks still need to see the original message. + errMessage := cmdErrorMessage(err) + + // Print the command's error before invoking plugin hooks so that the + // "What's next" hint (and any other hook output) is rendered after + // the command's error output, not before it. + if err != nil && !errdefs.IsCanceled(err) && !errors.As(err, &errCtxSignalTerminated{}) && err.Error() != "" { + _, _ = fmt.Fprintln(dockerCli.Err(), err) + // Replace the error with a status-only one so that main() + // does not print the same message a second time. + err = cli.StatusError{StatusCode: getExitCode(err)} + } + // If the command is being executed in an interactive terminal // and hook are enabled, run the plugin hooks. if subCommand != nil && dockerCli.Out().IsTerminal() && dockerCli.HooksEnabled() { - pluginmanager.RunCLICommandHooks(ctx, dockerCli, cmd, subCommand, cmdErrorMessage(err)) + pluginmanager.RunCLICommandHooks(ctx, dockerCli, cmd, subCommand, errMessage) } return err