{"record":{"id":"bf22cbbb82f270fa","repo":"charmbracelet/crush","slug":"invalid-hook-configuration-w","errorCode":null,"errorMessage":"invalid hook configuration: %w","messagePattern":"invalid hook configuration: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/load.go","lineNumber":85,"sourceCode":"\tif wsData, err := os.ReadFile(store.workspacePath); err == nil && len(wsData) > 0 {\n\t\tif !json.Valid(wsData) {\n\t\t\treturn nil, fmt.Errorf(\"invalid JSON in config file %s\", store.workspacePath)\n\t\t}\n\t\tmerged, mergeErr := loadFromBytes(append([][]byte{mustMarshalConfig(cfg)}, wsData))\n\t\tif mergeErr == nil {\n\t\t\t// Preserve defaults that setDefaults already applied.\n\t\t\tdataDir := cfg.Options.DataDirectory\n\t\t\t*cfg = *merged\n\t\t\tcfg.setDefaults(workingDir, dataDir)\n\t\t\tstore.config = cfg\n\t\t\tstore.loadedPaths = append(store.loadedPaths, store.workspacePath)\n\t\t}\n\t}\n\n\t// Validate hooks after all config merging is complete so workspace\n\t// hooks also get their matcher regexes compiled.\n\tif err := cfg.ValidateHooks(); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid hook configuration: %w\", err)\n\t}\n\n\tif !isInsideWorktree() {\n\t\tconst depth = 2\n\t\tconst items = 100\n\t\tslog.Warn(\"No git repository detected in working directory, will limit file walk operations\", \"depth\", depth, \"items\", items)\n\t\tassignIfNil(&cfg.Tools.Ls.MaxDepth, depth)\n\t\tassignIfNil(&cfg.Tools.Ls.MaxItems, items)\n\t\tassignIfNil(&cfg.Options.TUI.Completions.MaxDepth, depth)\n\t\tassignIfNil(&cfg.Options.TUI.Completions.MaxItems, items)\n\t}\n\n\tif isAppleTerminal() {\n\t\tslog.Warn(\"Detected Apple Terminal, enabling transparent mode\")\n\t\tassignIfNil(&cfg.Options.TUI.Transparent, true)\n\t}\n\n\t// Load known providers, this loads the config from catwalk. A failed","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/load.go#L67-L103","documentation":"After all config merging completes, Load() calls cfg.ValidateHooks() to compile hook matcher regexes and check hook definitions. Any hook-validation failure is wrapped with this message so the user knows the problem is in the hooks section of their config.","triggerScenarios":"Load() finishes merging global and workspace configs; ValidateHooks() returns an error such as an invalid matcher regex or malformed hook command/event definition defined in crushrc/crush.json.","commonSituations":"Typo in a hook event name; a preToolUse matcher regex that doesn't compile (e.g. unbalanced parenthesis '['); hook defined in workspace config overriding/breaking a valid global hook.","solutions":["Read the wrapped %w error to identify which hook failed and fix its definition","Check that every hook's matcher is a valid regular expression","Verify hook event names match supported events (see HOOKS.md)","Temporarily remove hooks from workspace config to isolate whether the global or workspace hook is at fault"],"exampleFix":"// before (crush.json)\n\"hooks\": {\"pre_tool_use\": [{\"matcher\": \"edit(\", \"command\": \"lint.sh\"}]}\n// after\n\"hooks\": {\"pre_tool_use\": [{\"matcher\": \"edit\", \"command\": \"lint.sh\"}]}","handlingStrategy":"validation","validationCode":"cfg, err := loadRawConfig()\nif err != nil { return err }\nif err := cfg.ValidateHooks(); err != nil {\n    return fmt.Errorf(\"hooks invalid before startup: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"store, err := config.Load(ctx, opts)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"invalid hook configuration:\") {\n        log.Fatalf(\"Fix hooks in crush config: %v\", err)\n    }\n    return err\n}","preventionTips":["Test hook matcher regexes with a regex tester before adding them to config","Keep hook event names against the documented list in HOOKS.md","Add hooks incrementally, running crush after each change","Keep global and workspace hooks separate to isolate failures"],"tags":["config","hooks","validation","regex"],"backgroundTag":"hook-configuration-invalid","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}