vitessio/vitess · error

cannot stat hook %v: %v

Error message

cannot stat hook %v: %v

What it means

os.Stat on the resolved hook path failed with an error other than NotExist (e.g. permission denied on a directory component, I/O error, or the path is not traversable). findHook returns HOOK_STAT_FAILED. Unlike HOOK_DOES_NOT_EXIST, the file may exist but cannot be inspected.

Source

Thrown at go/vt/hook/hook.go:119

func (hook *Hook) findHook(ctx context.Context) (*exec.Cmd, int, error) {
	// Find our root.
	root, err := vtenv.VtRoot()
	if err != nil {
		return nil, HOOK_VTROOT_ERROR, fmt.Errorf("cannot get VTROOT: %v", err)
	}

	// See if the hook exists.
	vthook, err := fileutil.SafePathJoin(filepath.Join(root, "vthook"), hook.Name)
	if err != nil {
		return nil, HOOK_INVALID_NAME, fmt.Errorf("invalid hook name %q: %v", hook.Name, err)
	}
	_, err = os.Stat(vthook)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, HOOK_DOES_NOT_EXIST, fmt.Errorf("missing hook %v", vthook)
		}

		return nil, HOOK_STAT_FAILED, fmt.Errorf("cannot stat hook %v: %v", vthook, err)
	}

	// Configure the command.
	log.Info(fmt.Sprintf("hook: executing hook: %v %v", vthook, strings.Join(hook.Parameters, " ")))
	cmd := exec.CommandContext(ctx, vthook, hook.Parameters...)
	if len(hook.ExtraEnv) > 0 {
		cmd.Env = os.Environ()
		for key, value := range hook.ExtraEnv {
			cmd.Env = append(cmd.Env, key+"="+value)
		}
	}

	return cmd, HOOK_SUCCESS, nil
}

// ExecuteContext tries to execute the Hook with the given context and returns a HookResult.
func (hook *Hook) ExecuteContext(ctx context.Context) (result *HookResult) {
	result = &HookResult{}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix filesystem permissions so the Vitess process can stat the hook path (chmod/chown the vthook dir and scripts)
  2. Inspect the trailing %v (the raw os.Stat error) to identify the exact OS-level cause
  3. Check for broken symlinks or a partially-deployed vthook directory and redeploy the hook

Example fix

// before: cannot stat hook: permission denied
// after
sudo chmod o+x $VTROOT/vthook
sudo chmod +x $VTROOT/vthook/myhook
Defensive patterns

Strategy: validation

Validate before calling

p := filepath.Join(os.Getenv("VTROOT"), "vthook", name)
if _, err := os.Stat(p); err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("cannot access hook %s: %v", p, err)
}

Try / catch

hr := h.ExecuteContext(ctx)
if hr.ExitStatus == hook.HOOK_STAT_FAILED {
    return fmt.Errorf("hook %s unusable (stat failed): %s", h.Name, hr.Stderr)
}

Prevention

When it happens

Trigger: Executing a hook when os.Stat on <VTROOT>/vthook/<name> returns a non-IsNotExist error — permission denied on vthook dir or file, broken symlink traversal errors, or filesystem I/O failures.

Common situations: vthook directory or script owned by another user without execute permission; NFS/permission misconfiguration in containers; corrupted symlink left by a failed deploy.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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