{"id":"daf9ce468b1c3f12","repo":"docker/cli","slug":"failed-to-parse-hook-template","errorCode":null,"errorMessage":"failed to parse hook template","messagePattern":"failed to parse hook template","errorType":"exception","errorClass":"ErrHookTemplateParse","httpStatus":null,"severity":"warning","filePath":"cli-plugins/hooks/template.go","lineNumber":49,"sourceCode":"\t\t\t\"arg\":  func(_ any, i int) (string, error) { return msgContext.argValue(i) },\n\t\t}).Parse(hookTemplate)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar b bytes.Buffer\n\t\terr = tmpl.Execute(&b, msgContext)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tout = b.String()\n\t}\n\tif n := strings.Count(out, \"\\n\"); n > maxMessages {\n\t\treturn nil, fmt.Errorf(\"hook template contains too many messages (%d): maximum is %d\", n, maxMessages)\n\t}\n\treturn strings.SplitN(out, \"\\n\", maxMessages), nil\n}\n\nvar ErrHookTemplateParse = errors.New(\"failed to parse hook template\")\n\n// commandInfo provides info about the command for which the hook was invoked.\n// It is used for templated hook-messages.\ntype commandInfo struct {\n\tcmd *cobra.Command\n}\n\n// Name returns the name of the (sub)command for which the hook was invoked.\n//\n// It's used for backward-compatibility with old templates.\nfunc (c commandInfo) Name() string {\n\treturn c.command()\n}\n\n// command returns the name of the (sub)command for which the hook was invoked.\nfunc (c commandInfo) command() string {\n\tif c.cmd == nil {\n\t\treturn \"\"","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/docker/cli/blob/e9452d6e785f6e365712b9d71bd7517591773c86/cli-plugins/hooks/template.go#L31-L67","documentation":"ErrHookTemplateParse is a sentinel error declared in cli-plugins/hooks/template.go for failures while parsing or executing a CLI plugin's hook message template. Docker CLI plugins (like buildx or scout) can return 'next steps' hint messages as Go text/template strings with custom functions ({{.Flag}}, {{flag}}, {{arg}}); if template.New(...).Parse or Execute fails on that string, template processing aborts and the hook's messages are dropped.","triggerScenarios":"A plugin's RunHook response contains a Template field with invalid Go template syntax (unclosed {{, unknown function, bad pipeline), or the template references a flag/arg that fails resolution during Execute via the flag()/arg() helper functions. Triggered inside hooks.ParseTemplate, called from cli-plugins/manager/hooks.go after a subcommand invocation matches a plugin's configured hook.","commonSituations":"Developers writing a CLI plugin with hook support ship a malformed template string; a plugin version mismatch where a newer template syntax (e.g. flag/arg helpers) is used against an older CLI; hand-edited plugin hook config in ~/.docker/config.json producing broken templates.","solutions":["Fix the template string returned by the plugin's hook handler so it is valid Go text/template syntax and only uses supported helpers (.Flag, flag, arg)","Validate the template locally with text/template Parse in a unit test before shipping the plugin","Upgrade the Docker CLI if the plugin relies on newer template helper functions","As a user, disable or update the offending plugin's hooks (remove the plugin hook entry in ~/.docker/config.json) until it is fixed"],"exampleFix":"// before (in plugin hook response)\nTemplate: \"Try: docker buildx {{ .Missing }\"\n// after\nTemplate: \"Try: docker buildx {{ .Flag }}\"","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["docker-cli","cli-plugins","hooks","go-template"],"analyzedSha":"e9452d6e785f6e365712b9d71bd7517591773c86","analyzedAt":"2026-08-01T07:09:22.474Z","schemaVersion":2}