chenhg5/cc-connect · error
POST only
Error message
POST only
What it means
The webhook endpoint only accepts HTTP POST. Any request with a different method (GET, PUT, DELETE, etc.) is rejected with 405 and body "POST only" before authentication is even attempted. This enforces the webhook contract, since payloads are carried in the POST body.
Source
Thrown at core/webhook.go:88
go func() {
slog.Info("webhook: server started", "addr", addr, "path", ws.path)
if err := ws.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("webhook: server error", "error", err)
}
}()
}
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
}View on GitHub (pinned to 4000b2338a)
Solutions
- Change the request method to POST.
- For health checks, configure the monitor to expect 405 or use a dedicated health endpoint.
- If the sender is a framework defaulting to another method, explicitly set method: 'POST'.
Example fix
// before
fetch(url)
// after
fetch(url, { method: "POST", headers: {"Authorization": "Bearer <token>", "Content-Type": "application/json"}, body: JSON.stringify({session_key: "s1", prompt: "hi"}) }) Defensive patterns
Strategy: validation
Validate before calling
if (typeof req.method === 'string' && req.method.toUpperCase() !== 'POST') {
throw new Error('webhook requires POST, got ' + req.method);
} Type guard
func isMethodNotAllowed(resp *http.Response) bool { return resp != nil && resp.StatusCode == http.StatusMethodNotAllowed } Try / catch
resp, err := http.Post(url, "application/json", body)
if err == nil && resp.StatusCode == 405 {
return errors.New("webhook endpoint only accepts POST — fix request method")
} Prevention
- Always construct webhook calls with http.Post / fetch method:'POST'
- Never 'test' the webhook URL in a browser (that sends GET)
- Configure monitors to hit a separate health endpoint
- Add a client-side assertion that the method is POST before dispatch
When it happens
Trigger: Sending GET/PUT/DELETE/OPTIONS to the WebhookServer's hook path — e.g. opening the URL in a browser (GET), a health-check prober hitting it with GET, or an API client defaulting to PUT.
Common situations: Verifying the webhook URL by pasting it in a browser; uptime monitors configured for GET; CORS preflight (OPTIONS) reaching the handler; REST clients set to PUT.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3a4630a41464c476.
Report an issue: GitHub.