{"record":{"id":"e8067426e3f04362","repo":"docker/cli","slug":"failed-to-unmarshal-hook-response-q-w","errorCode":null,"errorMessage":"failed to unmarshal hook response (%q): %w","messagePattern":"failed to unmarshal hook response \\(%q\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli-plugins/manager/hooks.go","lineNumber":91,"sourceCode":"\t\t}\n\n\t\tp, err := getPlugin(pluginName, pluginDirs, rootCmd)\n\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t}\n\n\t\tresp, err := p.RunHook(ctx, hooks.Request{\n\t\t\tRootCmd:      match,\n\t\t\tFlags:        flags,\n\t\t\tCommandError: cmdErrorMessage,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t}\n\n\t\tvar message hooks.Response\n\t\tif err := json.Unmarshal(resp, &message); err != nil {\n\t\t\treturn nil, false, fmt.Errorf(\"failed to unmarshal hook response (%q): %w\", string(resp), err)\n\t\t}\n\n\t\t// currently the only hook type\n\t\tif message.Type != hooks.NextSteps {\n\t\t\treturn nil, false, errors.New(\"unexpected hook response type: \" + strconv.Itoa(int(message.Type)))\n\t\t}\n\n\t\tmessages, err = hooks.ParseTemplate(message.Template, subCmd)\n\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t}\n\n\t\treturn messages, true, nil\n\t}\n\n\tfor pluginName, pluginCfg := range pluginsCfg {\n\t\tmessages, ok, err := tryInvokeHook(pluginName, pluginCfg)\n\t\tif err != nil {","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli-plugins/manager/hooks.go#L73-L109","documentation":"Thrown by the hook manager when json.Unmarshal fails to decode a plugin's hook response (hooks.Response) from the bytes returned by RunHook. The raw response text and the underlying json error are wrapped for diagnostics. A misbehaving plugin that returns non-JSON or a structurally wrong payload triggers it.","triggerScenarios":"A plugin hook executable that prints non-JSON to stdout, or emits JSON that does not match the hooks.Response schema (missing/extra fields, wrong types).","commonSituations":"Plugin writing debug/logs to stdout instead of stderr, returning a partial JSON object, or an older plugin using an incompatible response format.","solutions":["Ensure the plugin writes only the JSON Response payload to stdout (send logs to stderr).","Validate the response against the hooks.Response schema (Type and Template fields).","Update the plugin to the current hook protocol version."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if !json.Valid(resp) {\n    return fmt.Errorf(\"plugin %s returned non-JSON hook response\", pluginName)\n}","typeGuard":null,"tryCatchPattern":"var message hooks.Response\nif err := json.Unmarshal(resp, &message); err != nil {\n    logrus.WithError(err).WithField(\"plugin\", pluginName).Debug(\"skipping misbehaving plugin\")\n    continue // the manager already skips plugins on error\n}","preventionTips":["Plugins must emit only the JSON Response to stdout; send logs to stderr.","Keep plugins on the current hook protocol version.","Use json.Valid as a fast pre-check before unmarshal."],"tags":["hooks","cli-plugins","json","plugins"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}