{"record":{"id":"53fe417ec23fe65a","repo":"Leantime/leantime","slug":"32602-53fe41","errorCode":"-32602","errorMessage":"First day and last day are required","messagePattern":"First day and last day are required","errorType":"validation","errorClass":"Leantime\\Core\\Exceptions\\MissingParameterException","httpStatus":422,"severity":"error","filePath":"app/Domain/Sprints/Services/Sprints.php","lineNumber":255,"sourceCode":"            $this->authorize(SprintsPermissions::DELETE, (int) $sprint->projectId);\n        }\n\n        $this->sprintRepository->delSprint($id);\n\n        session(['currentSprint' => '']);\n    }\n\n    /**\n     * assertSprintDates - ensures the start and end date are both provided.\n     *\n     * @param  array  $params  Incoming sprint params.\n     *\n     * @throws MissingParameterException When the start or end date is missing.\n     */\n    private function assertSprintDates(array $params): void\n    {\n        if (($params['startDate'] ?? '') == '' || ($params['endDate'] ?? '') == '') {\n            throw new MissingParameterException('First day and last day are required');\n        }\n    }\n\n    /**\n     * @throws \\Exception\n     *\n     * @api\n     */\n    #[RequiresPermission(SprintsPermissions::VIEW)]\n    public function getSprintBurndown(Models\\Sprints $sprint): false|array\n    {\n\n        if (! is_object($sprint)) {\n            return false;\n        }\n\n        $sprintValues = $this->reportRepository->getSprintReport($sprint->id);\n        $sprintData = [];","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/Leantime/leantime/blob/9a9f49f1008f4782b30f6723c54228f4f992e636/app/Domain/Sprints/Services/Sprints.php#L237-L273","documentation":"Sprints::assertSprintDates() is invoked from both addSprint() (create, line 148) and editSprint() (line 191) and requires that BOTH 'startDate' and 'endDate' are present and non-empty in the params. The loose comparison ($params['startDate'] ?? '') == '' fails for a missing key, null, or empty string; other falsy values like '0' slip through. MissingParameterException maps to JSON-RPC -32602 (Invalid params).","triggerScenarios":"Creating a sprint from the roadmap without picking both dates; editing a sprint and clearing one of the two date fields; a JSON-RPC addSprint/editSprint call whose payload contains startDate but not endDate (or null instead of a date string).","commonSituations":"Date pickers left blank in the sprint dialog; frontend forms where one date is optional in the UI but required by the API; payloads built by spreading optional fields that end up null.","solutions":["Include both startDate and endDate (as parseable date strings) in every addSprint/editSprint payload","Make both date inputs required in the sprint form and validate before submit","Catch MissingParameterException (-32602) and highlight the missing date field in the UI"],"exampleFix":"// before\n$sprintsService->addSprint(['name' => 'Sprint 1', 'startDate' => '2026-08-20']);\n\n// after\n$sprintsService->addSprint([\n    'name' => 'Sprint 1',\n    'startDate' => '2026-08-20',\n    'endDate' => '2026-09-03',\n]);","handlingStrategy":"validation","validationCode":"if (trim((string) ($params['startDate'] ?? '')) === '' || trim((string) ($params['endDate'] ?? '')) === '') {\n    throw new \\InvalidArgumentException('Sprint start and end dates are both required');\n}","typeGuard":"/** @phpstan-assert array{startDate: non-empty-string, endDate: non-empty-string} $params */\nfunction hasBothSprintDates(array $params): bool\n{\n    return ($params['startDate'] ?? '') !== '' && ($params['endDate'] ?? '') !== '';\n}","tryCatchPattern":"try {\n    $sprintsService->addSprint($params);\n} catch (\\Leantime\\Core\\Exceptions\\MissingParameterException $e) {\n    // -32602: mark both date pickers as required in the dialog\n    $dialog->flagMissing(['startDate', 'endDate']);\n}","preventionTips":["Make both date pickers required in the sprint dialog and validate before submit","Send date strings (not null) for both fields even when only one changed","Applies to BOTH addSprint and editSprint — edit payloads need the dates too"],"tags":["sprints","validation","dates","json-rpc","missing-parameter"],"backgroundTag":"missing-required-parameter","analyzedSha":"9a9f49f1008f4782b30f6723c54228f4f992e636","analyzedAt":"2026-08-21T02:37:38.966Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}