chenhg5/cc-connect · error
session_key is required
Error message
session_key is required
What it means
HTTP 400 validation response from the webhook handler: the authenticated WebhookRequest JSON decoded successfully but its session_key field is empty, so the engine has no session to route the prompt or exec payload to.
Source
Thrown at core/webhook.go:104
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 != "" {
http.Error(w, "prompt and exec are mutually exclusive", http.StatusBadRequest)
return
}
engine, err := ws.resolveEngine(req.Project)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
eventName := req.EventView on GitHub (pinned to 4000b2338a)
Solutions
- Include a non-empty session_key in the JSON body (snake_case).
- Use the exact session key shown by the engine/session listing (e.g. /history or /sessions output).
- If key naming is the issue, rename sessionId → session_key in the payload.
- Client-side, reject payloads with empty session_key before dispatching the request.
Example fix
// before
{"prompt": "run tests"}
// after
{"session_key": "my-project:s1", "prompt": "run tests"} Defensive patterns
Strategy: validation
Validate before calling
func checkWebhookReq(r WebhookRequest) error {
if strings.TrimSpace(r.SessionKey) == "" { return errors.New("session_key is required") }
return nil
} Type guard
func hasSessionKey(p map[string]any) bool { k, ok := p["session_key"].(string); return ok && strings.TrimSpace(k) != "" } Try / catch
resp, err := http.Post(url, "application/json", bytes.NewReader(payload))
if err == nil && resp.StatusCode == 400 {
b, _ := io.ReadAll(resp.Body)
if strings.Contains(string(b), "session_key is required") {
return errors.New("add non-empty session_key (snake_case) to payload")
}
return fmt.Errorf("webhook rejected: %s", b)
} Prevention
- Use snake_case field names exactly as WebhookRequest defines them
- Validate session_key client-side before every send
- Derive session keys from a single helper, not ad-hoc strings
- Reuse keys returned by session listing APIs
When it happens
Trigger: POSTing a JSON object without the session_key key, or with "session_key": ""; sending a differently-named field (e.g. sessionId or sessionID) that the struct ignores.
Common situations: Client payloads written against an older/renamed API schema; builders omitting optional-looking fields; Go/JS clients using camelCase while the server expects snake_case.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- either prompt or exec is required
- invalid JSON:
- prompt and exec are mutually exclusive
- session_key is required
- err.Error()
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/8ebb7e72e7660bd9.
Report an issue: GitHub.