vitessio/vitess · error

process %v is still running

Error message

process %v is still running

What it means

cleanupLockfile detected that the PID recorded in the mysqld socket lock file is still alive, so it refuses to delete the lock file and returns 'process %v is still running'. This protects a running mysqld's lock from being stolen by a new instance.

Source

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

		return os.Remove(lockPath)
	}
	proc, err := os.FindProcess(p)
	if err != nil {
		log.Error(fmt.Sprintf("%v: error finding process: %v", ts, err))
		return err
	}
	err = proc.Signal(syscall.Signal(0))
	if err == nil {
		// If the process still exists, it's not safe to
		// remove the lock file, so we have to keep it around.
		cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", p))
		if err == nil {
			name := string(bytes.ReplaceAll(cmdline, []byte{0}, []byte(" ")))
			log.Error(fmt.Sprintf("%v: not removing socket lock file: %v with pid %v for %q", ts, lockPath, p, name))
		} else {
			log.Error(fmt.Sprintf("%v: not removing socket lock file: %v with pid %v (failed to read process name: %v)", ts, lockPath, p, err))
		}
		return fmt.Errorf("process %v is still running", p)
	}
	if !errors.Is(err, os.ErrProcessDone) {
		// Any errors except for the process being done
		// is unexpected here.
		log.Error(fmt.Sprintf("%v: error checking process %v: %v", ts, p, err))
		return err
	}

	// All good, process is gone and we can safely clean up the lock file.
	log.Info(fmt.Sprintf("%v: removing stale socket lock file: %v", ts, lockPath))
	return os.Remove(lockPath)
}

// Wait returns nil when mysqld is up and accepting connections. It
// will use the dba credentials to try to connect. Use wait() with
// different credentials if needed.
func (mysqld *Mysqld) Wait(ctx context.Context, cnf *Mycnf) error {
	params, err := mysqld.dbcfgs.DbaConnector().MysqlParams()

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check what process holds the PID: `ps -p <pid>` — if it's a live mysqld, stop it or use a different socket/port
  2. If the PID is reused by an unrelated process, remove the stale lock file manually after confirming mysqld is not running
  3. Clean up orphaned mysqld processes from failed previous starts
  4. Ensure prior vitess workflows terminate mysqld cleanly so locks are removed

Example fix

// before: start fails, lock file claims pid 1234 alive
ps -p 1234  # old mysqld still running
// after: stop it, then retry
mysqladmin -S /path/mysql.sock shutdown
# or if pid is reused and mysqld is gone:
rm /path/mysql.sock.lock
Defensive patterns

Strategy: validation

Validate before calling

lockPid := readPidFromLockFile(socketPath + ".lock")
if lockPid > 0 {
    if p, err := os.FindProcess(lockPid); err == nil && p.Signal(syscall.Signal(0)) == nil {
        return fmt.Errorf("pid %d still alive; not safe to start mysqld", lockPid)
    }
}

Try / catch

if err := mysqld.Start(ctx, cnf); err != nil && strings.Contains(err.Error(), "is still running") {
    // identify the pid from the error and inspect it before removing the lock
}

Prevention

When it happens

Trigger: Calling Mysqld.Start/Init (via startNoWait -> cleanupLockfile) when a lock file exists on the target socket path and the PID inside it belongs to a live process (Signal(0)/os.FindProcess check succeeds and err is not os.ErrProcessDone).

Common situations: A previous mysqld is genuinely still running on the same socket; orphaned mysqld after an aborted vtaction; PID reuse where a new unrelated process now owns the recorded PID; stale lock from an unclean shutdown whose PID happens to be recycled.

Related errors


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