{"record":{"id":"f5895a71b0ddeac3","repo":"locustio/locust","slug":"can-t-calculate-percentile-on-url-with-no-successf","errorCode":null,"errorMessage":"Can't calculate percentile on url with no successful requests","messagePattern":"Can't calculate percentile on url with no successful requests","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"locust/stats.py","lineNumber":659,"sourceCode":"                    cached = self.response_times_cache[ts]\n                    break\n\n        if cached:\n            # If we found an acceptable cached response times, we'll calculate a new response\n            # times dict of the last 10 seconds (approximately) by diffing it with the current\n            # total response times. Then we'll use that to calculate a response time percentile\n            # for that timeframe\n            return calculate_response_time_percentile(\n                diff_response_time_dicts(self.response_times, cached.response_times),\n                (self.num_requests - self.num_none_requests) - (cached.num_requests - cached.num_none_requests),\n                percent,\n            )\n        # if time was not in response times cache window\n        return None\n\n    def percentile(self) -> str:\n        if not self.num_requests:\n            raise ValueError(\"Can't calculate percentile on url with no successful requests\")\n\n        tpl = f\"%-{str(STATS_TYPE_WIDTH)}s %-{str(STATS_NAME_WIDTH)}s %8d {' '.join(['%6d'] * len(PERCENTILES_TO_REPORT))}\"\n\n        return tpl % (\n            (self.method or \"\", self.name)\n            + tuple(self.get_response_time_percentile(p) for p in PERCENTILES_TO_REPORT)\n            + (self.num_requests,)\n        )\n\n    def _cache_response_times(self, t: int) -> None:\n        if self.response_times_cache is None:\n            self.response_times_cache = OrderedDict()\n\n        self.response_times_cache[t] = CachedResponseTimes(\n            response_times=copy(self.response_times),\n            num_requests=self.num_requests,\n            num_none_requests=self.num_none_requests,\n        )","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/locustio/locust/blob/f391a716e12c2c712e80b5835e877b7933397453/locust/stats.py#L641-L677","documentation":"StatsEntry.percentile() formats a percentile report row and therefore needs at least one successful request; dividing/reading an empty response-time distribution would be meaningless, so it raises ValueError when num_requests is 0.","triggerScenarios":"Calling entry.percentile() on a stats entry for a URL/task that recorded zero successful requests — e.g. only failures, or a request that never fired.","commonSituations":"Custom console/CSV reporters iterating all entries at the end of a short test where some endpoints never got a 2xx; tests aborted early; entries for requests that only returned errors.","solutions":["Guard with 'if entry.num_requests:' before calling percentile()","Ensure the request actually succeeded at least once before reporting percentiles","Use entry.get_response_time_percentile only when num_requests > 0 or fall back to a placeholder value like 'N/A'"],"exampleFix":"// before\nrows.append(entry.percentile())\n// after\nif entry.num_requests:\n    rows.append(entry.percentile())\nelse:\n    rows.append(\"(no successful requests)\")","handlingStrategy":"validation","validationCode":"if entry.num_requests == 0:\n    return None  # skip percentile report","typeGuard":null,"tryCatchPattern":"try:\n    row = entry.percentile()\nexcept ValueError:\n    row = \"N/A\"","preventionTips":["Skip zero-request entries in custom reporters","Filter stats output to entries with successful requests","Check num_requests before any response-time computation"],"tags":["locust","stats","empty-data","percentiles"],"backgroundTag":"empty-dataset-percentile","analyzedSha":"f391a716e12c2c712e80b5835e877b7933397453","analyzedAt":"2026-08-29T00:36:13.872Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}