{"record":{"id":"06dc19729a096e78","repo":"vitessio/vitess","slug":"missing-hook-v","errorCode":null,"errorMessage":"missing hook %v","messagePattern":"missing hook (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/hook/hook.go","lineNumber":116,"sourceCode":"}\n\n// findHook tries to locate the hook, and returns the exec.Cmd for it.\nfunc (hook *Hook) findHook(ctx context.Context) (*exec.Cmd, int, error) {\n\t// Find our root.\n\troot, err := vtenv.VtRoot()\n\tif err != nil {\n\t\treturn nil, HOOK_VTROOT_ERROR, fmt.Errorf(\"cannot get VTROOT: %v\", err)\n\t}\n\n\t// See if the hook exists.\n\tvthook, err := fileutil.SafePathJoin(filepath.Join(root, \"vthook\"), hook.Name)\n\tif err != nil {\n\t\treturn nil, HOOK_INVALID_NAME, fmt.Errorf(\"invalid hook name %q: %v\", hook.Name, err)\n\t}\n\t_, err = os.Stat(vthook)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil, HOOK_DOES_NOT_EXIST, fmt.Errorf(\"missing hook %v\", vthook)\n\t\t}\n\n\t\treturn nil, HOOK_STAT_FAILED, fmt.Errorf(\"cannot stat hook %v: %v\", vthook, err)\n\t}\n\n\t// Configure the command.\n\tlog.Info(fmt.Sprintf(\"hook: executing hook: %v %v\", vthook, strings.Join(hook.Parameters, \" \")))\n\tcmd := exec.CommandContext(ctx, vthook, hook.Parameters...)\n\tif len(hook.ExtraEnv) > 0 {\n\t\tcmd.Env = os.Environ()\n\t\tfor key, value := range hook.ExtraEnv {\n\t\t\tcmd.Env = append(cmd.Env, key+\"=\"+value)\n\t\t}\n\t}\n\n\treturn cmd, HOOK_SUCCESS, nil\n}\n","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/hook/hook.go#L98-L134","documentation":"The hook name passed validation and SafePathJoin, but os.Stat found no file at <VTROOT>/vthook/<name>. findHook returns HOOK_DOES_NOT_EXIST with 'missing hook'. The name is legal; the script simply is not installed at the expected location.","triggerScenarios":"Executing a hook whose name resolves to a nonexistent file under $VTROOT/vthook — hook never deployed, name typo, or wrong VTROOT pointing at an installation without that hook.","commonSituations":"Typos in hook names in vttablet/vtworker config; hooks deployed on some nodes but not others; VTROOT pointing to a different (older) installation lacking the script.","solutions":["Install the hook script into $VTROOT/vthook/<name> (and make it executable)","Verify the hook name spelling matches the script file name exactly","Confirm VTROOT points at the installation that actually contains the hook (echo $VTROOT; ls $VTROOT/vthook)"],"exampleFix":"// before: HOOK_DOES_NOT_EXIST for 'gc_backup'\n// after\ncp myhooks/gc_backup.sh $VTROOT/vthook/gc_backup\nchmod +x $VTROOT/vthook/gc_backup","handlingStrategy":"validation","validationCode":"root, err := vtenv.VtRoot()\nif err != nil { return err }\np, err := fileutil.SafePathJoin(filepath.Join(root, \"vthook\"), name)\nif err != nil { return err }\nif _, err := os.Stat(p); os.IsNotExist(err) {\n    return fmt.Errorf(\"hook %s not installed at %s\", name, p)\n}","typeGuard":null,"tryCatchPattern":"hr := hook.ExecuteOptional(h)\nif hr.ExitStatus == hook.HOOK_DOES_NOT_EXIST {\n    log.Infof(\"hook %s not installed, skipping\", h.Name)\n    return nil\n}","preventionTips":["Deploy hook scripts to $VTROOT/vthook as part of provisioning (config-management managed)","Check HOOK_DOES_NOT_EXIST exit status to treat missing hooks as skippable via ExecuteOptional","Keep hook names consistent across all nodes of the cluster"],"tags":["hook","file-not-found","deployment"],"backgroundTag":"file-not-found","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}