chenhg5/cc-connect · error

unknown handler type %q (must be command or http)

Error message

unknown handler type %q (must be command or http)

What it means

validateHookConfig only accepts handler types "command" and "http". Any other Type value falls into the default branch and is rejected with this error naming the offending value. This catches typos and unsupported handler kinds early at HookManager construction.

Source

Thrown at core/hooks.go:124

func validateHookConfig(h HookConfig) error {
	if h.Event == "" {
		return fmt.Errorf("event is required")
	}
	switch HookHandlerType(h.Type) {
	case HookHandlerCommand:
		if h.Command == "" {
			return fmt.Errorf("command is required for type=command")
		}
	case HookHandlerHTTP:
		if h.URL == "" {
			return fmt.Errorf("url is required for type=http")
		}
		if !strings.HasPrefix(h.URL, "http://") && !strings.HasPrefix(h.URL, "https://") {
			return fmt.Errorf("url must start with http:// or https://")
		}
	default:
		return fmt.Errorf("unknown handler type %q (must be command or http)", h.Type)
	}
	return nil
}

// Emit dispatches an event to all matching hooks.
func (hm *HookManager) Emit(event HookEvent) {
	if hm == nil {
		return
	}
	event.Project = hm.project
	if event.Timestamp.IsZero() {
		event.Timestamp = time.Now()
	}

	hm.mu.RLock()
	hooks := hm.hooks
	hm.mu.RUnlock()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Set type = "command" for a shell-command hook or type = "http" for a webhook hook
  2. Fix the typo in the type value (check spelling against the two supported values)
  3. Remove the type key only if a default is documented and intended (empty type still fails)
  4. Consult the hooks documentation for the exact supported handler types

Example fix

// before (config.toml)
[[hooks]]
event = "before_agent"
type = "webhook"
url = "https://example.com/hook"
// after
[[hooks]]
event = "before_agent"
type = "http"
url = "https://example.com/hook"
Defensive patterns

Strategy: validation

Validate before calling

var validTypes = map[string]bool{"command": true, "http": true}
for i, h := range hooks {
    if !validTypes[h.Type] {
        return fmt.Errorf("hooks[%d]: unknown type %q (must be command or http)", i, h.Type)
    }
}

Try / catch

mgr, err := NewHookManager(hooks)
if err != nil {
    slog.Error("invalid hook config", "err", err)
    return fmt.Errorf("hook config: %w", err)
}

Prevention

When it happens

Trigger: NewHookManager receives a hook whose Type is any string other than "command" or "http" — e.g. type = "webhook", type = "script", type = "" (empty), or a misspelling like "comand".

Common situations: Guessing handler type names not in the supported set; typo in config.toml; copying hook config from another tool with different type vocabulary; leaving the type key empty.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/0c305a823901da4e. Report an issue: GitHub.