GoogleContainerTools/skaffold · error

SKAFFOLD_CMDLINE is invalid: %w

Error message

SKAFFOLD_CMDLINE is invalid: %w

What it means

When skaffold is invoked with no CLI args (len(os.Args)==1) and the SKAFFOLD_CMDLINE env var is set (used by phases like deploy/build to propagate the original command line to a re-executed binary), Run() attempts to shell-split that value. If shell.Split fails (unbalanced quotes, malformed escaping), the error is wrapped as `SKAFFOLD_CMDLINE is invalid`.

Source

Thrown at cmd/skaffold/app/skaffold.go:45

	shell "github.com/kballard/go-shellquote"

	"github.com/GoogleContainerTools/skaffold/v2/cmd/skaffold/app/cmd"
	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/output"
	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/output/log"
)

func Run(out, stderr io.Writer) error {
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGPIPE)
	defer cancel()

	catchStackdumpRequests()

	c := cmd.NewSkaffoldCommand(out, stderr)
	if cmdLine := os.Getenv("SKAFFOLD_CMDLINE"); cmdLine != "" && len(os.Args) == 1 {
		parsed, err := shell.Split(cmdLine)
		if err != nil {
			return fmt.Errorf("SKAFFOLD_CMDLINE is invalid: %w", err)
		}
		// XXX logged before logrus.SetLevel is called in NewSkaffoldCommand's PersistentPreRunE
		log.Entry(ctx).Debugf("Retrieving command line from SKAFFOLD_CMDLINE: %q", parsed)
		c.SetArgs(parsed)
	}
	c, err := c.ExecuteContextC(ctx)
	if err != nil {
		err = extractInvalidUsageError(err)
		if errors.Is(err, context.Canceled) {
			log.Entry(ctx).Debugln("ignore error since context is cancelled:", err)
		} else if !cmd.ShouldSuppressErrorReporting(c) {
			// As we allow some color setup using CLI flags for the main run, we can't run SetupColors()
			// for the entire skaffold run here. It's possible SetupColors() was never called, so call it again
			// before we print an error to get the right coloring.
			errOut := output.SetupColors(context.Background(), stderr, output.DefaultColorCode, false)
			output.Red.Fprintln(errOut, err)
		}
	}

View on GitHub (pinned to a1189de023)

Solutions

  1. Unset SKAFFOLD_CMDLINE (`unset SKAFFOLD_CMDLINE`) when invoking skaffold manually.
  2. Fix quoting in the value so it parses as shell tokens (balanced quotes/escapes).
  3. Run skaffold with explicit arguments instead of relying on the env var (len(os.Args)>1 skips this path).

Example fix

// before
export SKAFFOLD_CMDLINE='run --profile "dev'; skaffold
// after
unset SKAFFOLD_CMDLINE; skaffold run --profile dev
Defensive patterns

Strategy: try-catch

Validate before calling

if v, ok := os.LookupEnv("SKAFFOLD_CMDLINE"); ok && v != "" {
    if _, err := shell.Split(v); err != nil {
        os.Unsetenv("SKAFFOLD_CMDLINE")
    }
}

Try / catch

if err := runSkaffold(); err != nil {
    if strings.Contains(err.Error(), "SKAFFOLD_CMDLINE is invalid") {
        os.Unsetenv("SKAFFOLD_CMDLINE")
        err = runSkaffold()
    }
}

Prevention

When it happens

Trigger: Invoking the skaffold binary with zero arguments while SKAFFOLD_CMDLINE contains a string shell.Split cannot parse — e.g. dangling quote `skaffold run --tag "`, unbalanced parentheses, or manual export of a corrupted value.

Common situations: Manually exporting SKAFFOLD_CMDLINE in a shell/CI to test behavior; a parent skaffold process serializing a command line containing characters shell.Split rejects; wrapper scripts clobbering the env var.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/1a3fc4af370836fe. Report an issue: GitHub.