vitessio/vitess · error

%v: %w, output: %v

Error message

%v: %w, output: %v

What it means

execCmd runs an external command and captures combined stdout/stderr. If the command exits non-zero, the raw exec error is logged and then wrapped as '<command>: <exec error>, output: <combined output>' so operators can see exactly what the subprocess printed. This is a generic wrapper for failures of any external binary mysqlctl invokes (mysqld_safe, mysqladmin, mysqlinstall_db, etc.).

Source

Thrown at go/vt/mysqlctl/mysqld.go:1271

// execCmdWithContext searches the PATH for a command and runs it, logging the
// output. If input is not nil, pipe it to the command's stdin. If ctx is
// cancelled or its deadline passes, the command is killed and the call returns
// promptly rather than blocking on a stalled process.
func execCmdWithContext(ctx context.Context, name string, args, env []string, dir string, input io.Reader) (cmd *exec.Cmd, output string, err error) {
	cmdPath, _ := exec.LookPath(name)

	cmd = exec.CommandContext(ctx, cmdPath, args...)
	cmd.Env = env
	cmd.Dir = dir
	if input != nil {
		cmd.Stdin = input
	}
	out, err := cmd.CombinedOutput()
	output = string(out)
	if err != nil {
		log.Error(fmt.Sprintf("execCmd: %v failed: %v", name, err))
		err = fmt.Errorf("%v: %w, output: %v", name, err, output)
	}
	return cmd, output, err
}

// binaryPath does a limited path lookup for a command,
// searching only within sbin and bin in the given root.
func binaryPath(root, binary string) (string, error) {
	noSocketFile()
	subdirs := []string{"sbin", "bin", "libexec", "scripts"}
	for _, subdir := range subdirs {
		binPath := path.Join(root, subdir, binary)
		if _, err := os.Stat(binPath); err == nil {
			return binPath, nil
		}
	}
	return "", fmt.Errorf("%s not found in any of %s/{%s}",
		binary, root, strings.Join(subdirs, ","))
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Read the 'output:' portion of the error — it contains the child process's own diagnostic (e.g. mysqld's config error).
  2. Fix the specific issue reported by the child (my.cnf directive, permissions, data dir state).
  3. Verify the binary exists in the expected root bin/sbin directory and matches the expected MySQL flavor/version.
  4. Check disk space and inode availability on the data/log directories.

Example fix

// before: mysqld_safe exits, output shows unknown variable
[ERROR] mysqld: unknown variable 'innodb_fake=1'
// after: remove the bad directive from my.cnf
innodb_flush_method = O_DIRECT
Defensive patterns

Strategy: try-catch

Validate before calling

out, err := exec.Command(name, args...).CombinedOutput()
if err != nil {
    log.Errorf("%s failed: %v, output: %s", name, err, out)
}

Type guard

func isCmdError(err error, cmdName string) bool {
    return err != nil && strings.HasPrefix(err.Error(), cmdName+":")
}

Try / catch

cmd, output, err := execCmd(ctx, 10*time.Second, "mysqld", args...)
if err != nil {
    // output holds the child's own diagnostics; surface it to operators
    return fmt.Errorf("mysqld launch failed: %w (output: %s)", err, output)
}

Prevention

When it happens

Trigger: Any execCmd call (e.g. launching mysqld, running mysqladmin shutdown, initialize scripts) where the spawned binary exits non-zero — the command name, underlying error, and its combined output are wrapped into the returned error.

Common situations: mysqld fails to start due to a bad my.cnf; mysqladmin fails authentication; required binaries missing or wrong version in the vt root bin/sbin dirs; disk full so the data directory cannot be initialized.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/ddf01e4b3a029430. Report an issue: GitHub.