{"record":{"id":"634894f2505314f0","repo":"chenhg5/cc-connect","slug":"event-is-required","errorCode":null,"errorMessage":"event is required","messagePattern":"event is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/hooks.go","lineNumber":109,"sourceCode":"\t\tif err := validateHookConfig(h); err != nil {\n\t\t\tslog.Warn(\"hooks: skipping invalid config\", \"project\", project, \"error\", err)\n\t\t\tcontinue\n\t\t}\n\t\tvalid = append(valid, h)\n\t}\n\treturn &HookManager{\n\t\thooks:       valid,\n\t\tproject:     project,\n\t\tshell:       shell,\n\t\tshellFlag:   shellFlag,\n\t\tshellProfile: shellProfile,\n\t\tclient:      &http.Client{},\n\t}\n}\n\nfunc validateHookConfig(h HookConfig) error {\n\tif h.Event == \"\" {\n\t\treturn fmt.Errorf(\"event is required\")\n\t}\n\tswitch HookHandlerType(h.Type) {\n\tcase HookHandlerCommand:\n\t\tif h.Command == \"\" {\n\t\t\treturn fmt.Errorf(\"command is required for type=command\")\n\t\t}\n\tcase HookHandlerHTTP:\n\t\tif h.URL == \"\" {\n\t\t\treturn fmt.Errorf(\"url is required for type=http\")\n\t\t}\n\t\tif !strings.HasPrefix(h.URL, \"http://\") && !strings.HasPrefix(h.URL, \"https://\") {\n\t\t\treturn fmt.Errorf(\"url must start with http:// or https://\")\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown handler type %q (must be command or http)\", h.Type)\n\t}\n\treturn nil\n}","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/hooks.go#L91-L127","documentation":"validateHookConfig in core/hooks.go checks each HookConfig before a HookManager accepts it. Every hook must declare which event it listens for; an empty Event field is rejected with this error. This runs when NewHookManager is constructed (e.g. from parsed config.toml hooks entries).","triggerScenarios":"Creating a NewHookManager with a hook entry whose Event field is the empty string — e.g. a [[hooks]] table in config.toml missing the event key, or a programmatically built HookConfig with Event left unset.","commonSituations":"config.toml hook entry missing the `event` key; typo of the field name so it fails to unmarshal; building hooks in code and forgetting to set Event.","solutions":["Add the `event` key to the hook entry in config.toml (e.g. event = \"before_agent\")","Check the field name spelling matches the HookConfig struct's expected key","Set h.Event programmatically before constructing the HookManager","Consult the docs for the list of valid hook event names"],"exampleFix":"// before (config.toml)\n[[hooks]]\ntype = \"command\"\ncommand = \"/scripts/notify.sh\"\n// after\n[[hooks]]\nevent = \"after_agent\"\ntype = \"command\"\ncommand = \"/scripts/notify.sh\"","handlingStrategy":"validation","validationCode":"for i, h := range hooks {\n    if h.Event == \"\" {\n        return fmt.Errorf(\"hooks[%d]: event is required\", i)\n    }\n}","typeGuard":null,"tryCatchPattern":"mgr, err := NewHookManager(hooks)\nif err != nil {\n    slog.Error(\"invalid hook config\", \"err\", err)\n    return fmt.Errorf(\"hook config: %w\", err)\n}","preventionTips":["Always include the `event` key in every [[hooks]] config entry","Validate hook config at deploy time, not just at daemon start","Keep a copy-paste-ready hook template in docs","Strict TOML decoding surfaces misspelled keys — prefer it"],"tags":["hooks","validation","config"],"backgroundTag":"missing-required-config-field","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}