{"record":{"id":"d407ce7bcc251ab6","repo":"chenhg5/cc-connect","slug":"err-error-d407ce","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"core/webhook.go","lineNumber":118,"sourceCode":"\t\treturn\n\t}\n\n\tif req.SessionKey == \"\" {\n\t\thttp.Error(w, \"session_key is required\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tif req.Prompt == \"\" && req.Exec == \"\" {\n\t\thttp.Error(w, \"either prompt or exec is required\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tif req.Prompt != \"\" && req.Exec != \"\" {\n\t\thttp.Error(w, \"prompt and exec are mutually exclusive\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tengine, err := ws.resolveEngine(req.Project)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\teventName := req.Event\n\tif eventName == \"\" {\n\t\teventName = \"webhook\"\n\t}\n\n\tslog.Info(\"webhook: received\",\n\t\t\"event\", eventName,\n\t\t\"project\", req.Project,\n\t\t\"session_key\", req.SessionKey,\n\t\t\"has_prompt\", req.Prompt != \"\",\n\t\t\"has_exec\", req.Exec != \"\",\n\t)\n\n\tif req.Exec != \"\" {\n\t\tgo ws.executeShell(engine, req, eventName)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/webhook.go#L100-L136","documentation":"`ws.resolveEngine(req.Project)` failed — the requested project could not be mapped to a running engine — and its error text is returned verbatim with 400. This typically means the project name in the payload doesn't match any configured/registered project.","triggerScenarios":"req.Project set to a name not present in the webhook server's project registry; empty project when no default project is configured; project service not yet started when the request arrives.","commonSituations":"Typo in the project name (case-sensitive mismatch); config.toml lists a project the server doesn't register; sending project for a single-project deployment that ignores it.","solutions":["Use the exact project name from config.toml / engine registration (check case).","Omit the project field if you run a single project and no default is required.","Verify the engine for that project started successfully before sending webhooks.","Inspect resolveEngine to confirm how project names are keyed and match accordingly."],"exampleFix":"// before\n{\"session_key\":\"s1\",\"prompt\":\"hi\",\"project\":\"myapp\"}   // config has [projects.my-app]\n// after\n{\"session_key\":\"s1\",\"prompt\":\"hi\",\"project\":\"my-app\"}","handlingStrategy":"validation","validationCode":"var knownProjects = map[string]bool{\"my-app\": true}\nfunc checkProject(p string) error {\n    if p != \"\" && !knownProjects[p] { return fmt.Errorf(\"unknown project %q\", p) }\n    return nil\n}","typeGuard":"func isProjectNotFound(resp *http.Response) bool {\n    if resp == nil || resp.StatusCode != 400 { return false }\n    b, _ := io.ReadAll(resp.Body)\n    return strings.Contains(strings.ToLower(string(b)), \"project\")\n}","tryCatchPattern":"resp, err := http.Post(url, \"application/json\", bytes.NewReader(payload))\nif err == nil && resp.StatusCode == 400 {\n    b, _ := io.ReadAll(resp.Body)\n    return fmt.Errorf(\"resolveEngine rejected project: %s\", b) // body carries the reason\n}","preventionTips":["Copy project names from config.toml verbatim, not from memory","Keep a client-side list of valid project names and validate before sending","Confirm the engine for the project is running before dispatching hooks","Watch for case-sensitive mismatches between payload and config"],"tags":["webhook","project-resolution","http-400","config"],"backgroundTag":"resource-not-found","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}