diff --git a/driver.go b/driver.go
index 6fdb8dbcfdf00543d882b0a6a5a22de6c552cd51..02f4b82015b4f08b85e77b378b48d759c3af1c40 100644
--- a/driver.go
+++ b/driver.go
@@ -243,6 +243,10 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
 // SetConfigFromFlags handles additional driver arguments as retrieved by [Driver.GetCreateFlags];
 // see [drivers.Driver.SetConfigFromFlags]
 func (d *Driver) SetConfigFromFlags(opts drivers.DriverOptions) error {
+	return d.setConfigFromFlags(opts)
+}
+
+func (d *Driver) setConfigFromFlagsImpl(opts drivers.DriverOptions) error {
 	d.AccessToken = opts.String(flagAPIToken)
 	d.Image = opts.String(flagImage)
 	d.ImageID = opts.Int(flagImageID)
@@ -267,7 +271,7 @@ func (d *Driver) SetConfigFromFlags(opts drivers.DriverOptions) error {
 	d.placementGroup = opts.String(flagPlacementGroup)
 	if opts.Bool(flagAutoSpread) {
 		if d.placementGroup != "" {
-			return errors.Errorf(flagAutoSpread + " and " + flagPlacementGroup + " are mutually exclusive")
+			return d.flagFailure("%v and %v are mutually exclusive", flagAutoSpread, flagPlacementGroup)
 		}
 		d.placementGroup = autoSpreadPgName
 	}
@@ -280,17 +284,17 @@ func (d *Driver) SetConfigFromFlags(opts drivers.DriverOptions) error {
 	d.SetSwarmConfigFromFlags(opts)
 
 	if d.AccessToken == "" {
-		return errors.Errorf("hetzner requires --%v to be set", flagAPIToken)
+		return d.flagFailure("hetzner requires --%v to be set", flagAPIToken)
 	}
 
 	if d.ImageID != 0 && d.Image != "" && d.Image != defaultImage /* support legacy behaviour */ {
-		return errors.Errorf("--%v and --%v are mutually exclusive", flagImage, flagImageID)
+		return d.flagFailure("--%v and --%v are mutually exclusive", flagImage, flagImageID)
 	} else if d.ImageID == 0 && d.Image == "" {
 		d.Image = defaultImage
 	}
 
 	if d.DisablePublic4 && d.DisablePublic6 && !d.UsePrivateNetwork {
-		return errors.Errorf("--%v must be used if public networking is disabled (hint: implicitly set by --%v)",
+		return d.flagFailure("--%v must be used if public networking is disabled (hint: implicitly set by --%v)",
 			flagUsePrivateNetwork, flagDisablePublic)
 	}
 
@@ -312,7 +316,7 @@ func (d *Driver) setLabelsFromFlags(opts drivers.DriverOptions) error {
 	for _, label := range opts.StringSlice(flagServerLabel) {
 		split := strings.SplitN(label, "=", 2)
 		if len(split) != 2 {
-			return errors.Errorf("server label %v is not in key=value format", label)
+			return d.flagFailure("server label %v is not in key=value format", label)
 		}
 		d.ServerLabels[split[0]] = split[1]
 	}
@@ -331,7 +335,7 @@ func (d *Driver) setLabelsFromFlags(opts drivers.DriverOptions) error {
 func (d *Driver) PreCreateCheck() error {
 	if d.IsExistingKey {
 		if d.originalKey == "" {
-			return errors.New("specifying an existing key ID requires the existing key path to be set as well")
+			return d.flagFailure("specifying an existing key ID requires the existing key path to be set as well")
 		}
 
 		key, err := d.getKey()
diff --git a/flag_failure.go b/flag_failure.go
new file mode 100644
index 0000000000000000000000000000000000000000..b58ded33caf3b300aaa3172b5798823e16bc4f20
--- /dev/null
+++ b/flag_failure.go
@@ -0,0 +1,16 @@
+//go:build !flag_debug
+
+package main
+
+import (
+	"github.com/docker/machine/libmachine/drivers"
+	"github.com/pkg/errors"
+)
+
+func (d *Driver) flagFailure(format string, args ...interface{}) error {
+	return errors.Errorf(format, args...)
+}
+
+func (d *Driver) setConfigFromFlags(opts drivers.DriverOptions) error {
+	return d.setConfigFromFlagsImpl(opts)
+}
diff --git a/flag_failure_debug.go b/flag_failure_debug.go
new file mode 100644
index 0000000000000000000000000000000000000000..3d25f404d222bcc61fcf981c722912b9f9396644
--- /dev/null
+++ b/flag_failure_debug.go
@@ -0,0 +1,32 @@
+//go:build flag_debug
+
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/docker/machine/libmachine/drivers"
+	"github.com/pkg/errors"
+)
+
+var lastOpts drivers.DriverOptions
+
+func (d *Driver) flagFailure(format string, args ...interface{}) error {
+	// machine driver may not flush logs received when getting an RPC error, so we have to resort to this terribleness
+	line1 := fmt.Sprintf("Flag failure detected:\n -> last opts: %v\n -> driver state %v", lastOpts, d)
+	var line2 string
+	if out, err := json.MarshalIndent(d, "", "  "); err == nil {
+		line2 = fmt.Sprintf(" -> driver json:\n%s", out)
+	} else {
+		line2 = fmt.Sprintf("could not encode driver json: %v", err)
+	}
+
+	combined := append([]interface{}{line1, line2}, args...)
+	return errors.Errorf("%s\n%s\n"+format, combined...)
+}
+
+func (d *Driver) setConfigFromFlags(opts drivers.DriverOptions) error {
+	lastOpts = opts
+	return d.setConfigFromFlagsImpl(opts)
+}