{"record":{"id":"94c914aa35b53f6d","repo":"docker/cli","slug":"hook-template-contains-too-many-messages-d-max","errorCode":null,"errorMessage":"hook template contains too many messages (%d): maximum is %d","messagePattern":"hook template contains too many messages \\((.+?)\\): maximum is (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli-plugins/hooks/template.go","lineNumber":44,"sourceCode":"\t\t\t\"flagValue\": msgContext.flagValue,\n\t\t\t\"argValue\":  msgContext.argValue,\n\n\t\t\t// kept for backward-compatibility with old templates.\n\t\t\t\"flag\": func(_ any, flagName string) (string, error) { return msgContext.flagValue(flagName) },\n\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}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli-plugins/hooks/template.go#L26-L62","documentation":"Thrown by hooks.ParseTemplate after template expansion when the rendered output contains more than maxMessages (10) newline-separated messages. Hook messages are appended as next-steps hints; a runaway template emitting many lines would flood the output, so a hard cap of 10 is enforced.","triggerScenarios":"A plugin hook template whose expansion produces >10 lines, e.g. iterating over many items or embedding a multi-line blob. The check counts newlines in the post-expansion string.","commonSituations":"A hook template that ranges over a large list, or includes a literal multi-line document. Bumping content during plugin development can cross the 10-line threshold unexpectedly.","solutions":["Reduce the template output to at most 10 newline-separated messages.","Replace iteration over large lists with a summarized single message.","Move long-form content out of the hook (e.g. link to docs) instead of printing it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// after expanding the template yourself, count newlines\nif strings.Count(expanded, \"\\n\") > 10 {\n    return fmt.Errorf(\"template yields %d messages; max is 10\", strings.Count(expanded, \"\\n\"))\n}","typeGuard":null,"tryCatchPattern":"msgs, err := hooks.ParseTemplate(tpl, cmd)\nif err != nil {\n    // degrade gracefully, skip next-steps\n    return nil\n}","preventionTips":["Keep hook templates to at most 10 newline-separated messages.","Summarize multi-line output rather than dumping it."],"tags":["hooks","cli-plugins","template","validation"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}