{"record":{"id":"d3838764219dfc0a","repo":"helm/helm","slug":"unknown-wait-strategy-s-s-valid-values-are-wat","errorCode":null,"errorMessage":"unknown wait strategy (s%s). Valid values are: watcher, hookOnly, legacy","messagePattern":"unknown wait strategy \\(s(.+?)\\)\\. Valid values are: watcher, hookOnly, legacy","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/kube/client.go","lineNumber":209,"sourceCode":"\tswitch strategy {\n\tcase LegacyStrategy:\n\t\tkc, err := c.Factory.KubernetesClientSet()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &legacyWaiter{kubeClient: kc, ctx: c.WaitContext}, nil\n\tcase StatusWatcherStrategy:\n\t\treturn c.newStatusWatcher(opts...)\n\tcase HookOnlyStrategy:\n\t\tsw, err := c.newStatusWatcher(opts...)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &hookOnlyWaiter{sw: sw}, nil\n\tcase \"\":\n\t\treturn nil, errors.New(\"wait strategy not set. Choose one of: \" + string(StatusWatcherStrategy) + \", \" + string(HookOnlyStrategy) + \", \" + string(LegacyStrategy))\n\tdefault:\n\t\treturn nil, errors.New(\"unknown wait strategy (s\" + string(strategy) + \"). Valid values are: \" + string(StatusWatcherStrategy) + \", \" + string(HookOnlyStrategy) + \", \" + string(LegacyStrategy))\n\t}\n}\n\nfunc (c *Client) SetWaiter(ws WaitStrategy) error {\n\treturn c.SetWaiterWithOptions(ws)\n}\n\nfunc (c *Client) SetWaiterWithOptions(ws WaitStrategy, opts ...WaitOption) error {\n\tvar err error\n\tc.Waiter, err = c.GetWaiterWithOptions(ws, opts...)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// New creates a new Client.\nfunc New(getter genericclioptions.RESTClientGetter) *Client {","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/pkg/kube/client.go#L191-L227","documentation":"Returned by Client.GetWaiterWithOptions (pkg/kube/client.go:209) when the strategy string matches none of the three known values: watcher, hookOnly, legacy. Note the message is built by concatenation and contains a stray literal 's' — it renders as \"unknown wait strategy (s<value>). Valid values are: ...\" — a cosmetic quirk, but the valid-value list it prints is authoritative.","triggerScenarios":"c.SetWaiter(kube.WaitStrategy(\"polling\")), \"watch\", \"Watcher\", or any typo/case variant — anything not exactly watcher, hookOnly, or legacy hits the default branch.","commonSituations":"Migrating configuration from other tools or old Helm versions with different strategy names; case mismatches; trailing whitespace in config strings; hand-typed values instead of the exported constants.","solutions":["Use the exported constants kube.StatusWatcherStrategy / kube.HookOnlyStrategy / kube.LegacyStrategy instead of raw strings","Trim and validate the string against the three allowed values before calling SetWaiter","Fix typos/case: the matcher is exact (watcher, not Watcher or watch)"],"exampleFix":"// before\nc.SetWaiter(kube.WaitStrategy(strings.TrimSpace(cfg.WaitStrategy)))\n\n// after — validate then use constants\nswitch strings.TrimSpace(cfg.WaitStrategy) {\ncase string(kube.StatusWatcherStrategy), string(kube.HookOnlyStrategy), string(kube.LegacyStrategy):\n    c.SetWaiter(kube.WaitStrategy(strings.TrimSpace(cfg.WaitStrategy)))\ndefault:\n    return fmt.Errorf(\"invalid wait strategy %q\", cfg.WaitStrategy)\n}","handlingStrategy":"validation","validationCode":"var allowedStrategies = map[kube.WaitStrategy]bool{\n    kube.StatusWatcherStrategy: true,\n    kube.HookOnlyStrategy:      true,\n    kube.LegacyStrategy:        true,\n}\nif !allowedStrategies[kube.WaitStrategy(cfg.WaitStrategy)] {\n    return fmt.Errorf(\"invalid wait strategy %q (want watcher, hookOnly, or legacy)\", cfg.WaitStrategy)\n}","typeGuard":"func isValidWaitStrategy(s string) bool {\n    switch strings.TrimSpace(s) {\n    case \"watcher\", \"hookOnly\", \"legacy\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := c.SetWaiterWithOptions(ws); err != nil {\n    if strings.Contains(err.Error(), \"unknown wait strategy\") {\n        return fmt.Errorf(\"config: %q is not a Helm v4 wait strategy (watcher|hookOnly|legacy): %w\", ws, err)\n    }\n    return err\n}","preventionTips":["Normalize (trim, lowercase-with-care: hookOnly is camel) and validate user input before SetWaiter","Use exported constants everywhere in code; strings only at the config boundary","Note the message's stray 's' quirk — don't parse the error text, validate up front"],"tags":["kubernetes","helm","wait-strategy","validation","typo"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}