{"record":{"id":"07ad1a9926a3328b","repo":"Leantime/leantime","slug":"this-endpoint-only-supports-patch-requests","errorCode":null,"errorMessage":"This endpoint only supports PATCH requests","messagePattern":"This endpoint only supports PATCH requests","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"app/Domain/Projects/Hxcontrollers/Checklist.php","lineNumber":34,"sourceCode":"    /**\n     * Controller constructor\n     *\n     * @param  Projects  $projectService  The projects domain service.\n     */\n    public function init(Projects $projectService): void\n    {\n        $this->projectService = $projectService;\n    }\n\n    /**\n     * Updates subtask status\n     *\n     * @throws BindingResolutionException\n     */\n    public function updateSubtask(): void\n    {\n        if (! $this->incomingRequest->getMethod() == 'PATCH') {\n            throw new Error('This endpoint only supports PATCH requests');\n        }\n\n        // update project progress\n        $projectProgress = $this->incomingRequest->request->all();\n\n        $this->projectService->updateProjectProgress($projectProgress, session('currentProject'));\n\n        // return view with new data\n        [$progressSteps, $percentDone] = $this->projectService->getProjectSetupChecklist(session('currentProject'));\n        $this->tpl->assign('progressSteps', $progressSteps);\n        $this->tpl->assign('percentDone', $percentDone);\n        $this->tpl->assign('includeTitle', false);\n    }\n}\n","sourceCodeStart":16,"sourceCodeEnd":49,"githubUrl":"https://github.com/Leantime/leantime/blob/9a9f49f1008f4782b30f6723c54228f4f992e636/app/Domain/Projects/Hxcontrollers/Checklist.php#L16-L49","documentation":"The guard in Checklist::updateSubtask() intends to reject non-PATCH requests, but the condition is written as `! $this->incomingRequest->getMethod() == 'PATCH'`. PHP parses this as `(!getMethod()) == 'PATCH'`: negating a non-empty string yields false, and false == 'PATCH' is false, so the if-branch never executes and the \\Error is unreachable dead code. In practice /hx/projects/checklist/updateSubtask currently accepts every HTTP verb — the advertised restriction does not exist.","triggerScenarios":"None as written — the error can never fire. It would only trigger for GET/POST/etc. requests if the operator were corrected to !==. Meanwhile any verb reaching the endpoint proceeds to updateProjectProgress().","commonSituations":"Developers reading the message and assuming verb enforcement exists (e.g., when auditing an HTMX endpoint); relying on this guard as a security control; adding hx-post/hx-get callers that unexpectedly succeed against a 'PATCH-only' endpoint.","solutions":["Fix the comparison to $this->incomingRequest->getMethod() !== 'PATCH' so the guard actually runs","Prefer enforcing the verb at the route/routing layer and deleting the broken inline guard","If this endpoint is exposed to untrusted callers, treat the missing method restriction as a real defect and patch it before shipping"],"exampleFix":"// before\nif (! $this->incomingRequest->getMethod() == 'PATCH') {\n    throw new Error('This endpoint only supports PATCH requests');\n}\n\n// after\nif ($this->incomingRequest->getMethod() !== 'PATCH') {\n    throw new Error('This endpoint only supports PATCH requests');\n}","handlingStrategy":"validation","validationCode":"// client side (htmx does this for you with hx-patch)\nif (fetchParams.method !== 'PATCH') {\n    throw new Error('updateSubtask requires PATCH');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use hx-patch (not hx-post/hx-get) on elements hitting /hx/projects/checklist/updateSubtask","Do not trust the in-controller guard — as written it is dead code; enforce the verb at your route or proxy if it matters","When copying this pattern into new controllers, write !== from the start"],"tags":["htmx","http-method","operator-precedence","dead-code","php"],"backgroundTag":"http-method-not-allowed","analyzedSha":"9a9f49f1008f4782b30f6723c54228f4f992e636","analyzedAt":"2026-08-21T02:37:38.966Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}