chenhg5/cc-connect · error

unauthorized

Error message

unauthorized

What it means

HTTP 401 response from the webhook handler: the request failed the server's authenticate check (missing, malformed, or wrong shared secret/token), so the inbound prompt/exec request is rejected before decoding.

Source

Thrown at core/webhook.go:93

	}()
}

func (ws *WebhookServer) Stop() {
	if ws.server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		_ = ws.server.Shutdown(ctx)
	}
}

func (ws *WebhookServer) handleHook(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	if !ws.authenticate(r) {
		http.Error(w, "unauthorized", http.StatusUnauthorized)
		return
	}

	var req WebhookRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}

	if req.SessionKey == "" {
		http.Error(w, "session_key is required", http.StatusBadRequest)
		return
	}
	if req.Prompt == "" && req.Exec == "" {
		http.Error(w, "either prompt or exec is required", http.StatusBadRequest)
		return
	}
	if req.Prompt != "" && req.Exec != "" {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Add the correct Authorization header (Bearer <webhook-token>) matching the server's configured secret.
  2. Re-copy the token from config.toml after any change and restart/refresh the caller.
  3. Check for stray whitespace/quotes in the token in both config and client.
  4. Confirm the token actually reached the server (log headers server-side at debug level).

Example fix

// before
curl -X POST http://127.0.0.1:8849/hook -d '{"prompt":"hi"}'
// after
curl -X POST http://127.0.0.1:8849/hook -H "Authorization: Bearer $WEBHOOK_TOKEN" -d '{"session_key":"s1","prompt":"hi"}'
Defensive patterns

Strategy: validation

Validate before calling

func webhookPayload(url, token string) error {
    if token == "" { return errors.New("missing webhook token") }
    req, _ := http.NewRequest(http.MethodPost, url, nil)
    req.Header.Set("Authorization", "Bearer "+token)
    return nil // inspect req before send
}

Type guard

func isUnauthorized(resp *http.Response) bool { return resp != nil && resp.StatusCode == http.StatusUnauthorized }

Try / catch

resp, err := client.Do(req)
if err == nil && resp.StatusCode == 401 {
    return fmt.Errorf("webhook auth failed: token mismatch with WebhookServer secret")
}

Prevention

When it happens

Trigger: POSTing to the hook endpoint without an Authorization header, with a wrong Bearer token, or with a token that does not match the WebhookServer's configured secret.

Common situations: Secret rotated in config but the calling service still uses the old one; curl test forgot the auth header; webhook sender configured without credentials; token copy-pasted with whitespace or quotes.

Understand the failure class

Related errors


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