{"record":{"id":"d66d3f6e7563775e","repo":"SonarSource/sonarqube","slug":"metrics-s-are-not-found","errorCode":null,"errorMessage":"Metrics %s are not found","messagePattern":"Metrics (.+?) are not found","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java","lineNumber":268,"sourceCode":"    SnapshotQuery dbQuery = new SnapshotQuery()\n      .setRootComponentUuid(component.branchUuid())\n      .setStatus(STATUS_PROCESSED)\n      .setSort(SORT_FIELD.BY_DATE, SORT_ORDER.ASC);\n    ofNullable(request.getFrom()).ifPresent(from -> dbQuery.setCreatedAfter(parseStartingDateOrDateTime(from).getTime()));\n    ofNullable(request.getTo()).ifPresent(to -> dbQuery.setCreatedBefore(parseEndingDateOrDateTime(to).getTime() + 1_000L));\n\n    return dbClient.snapshotDao().selectAnalysesByQuery(dbSession, dbQuery);\n  }\n\n  private List<MetricDto> searchMetrics(DbSession dbSession, SearchHistoryRequest request) {\n    List<String> upToDateRequestedMetrics = RemovedMetricConverter.withRemovedMetricAlias(request.getMetrics());\n    List<MetricDto> metrics = dbClient.metricDao().selectByKeys(dbSession, upToDateRequestedMetrics);\n    if (upToDateRequestedMetrics.size() > metrics.size()) {\n      Set<String> requestedMetrics = new HashSet<>(upToDateRequestedMetrics);\n      Set<String> foundMetrics = metrics.stream().map(MetricDto::getKey).collect(Collectors.toSet());\n\n      Set<String> unfoundMetrics = Sets.difference(requestedMetrics, foundMetrics).immutableCopy();\n      throw new IllegalArgumentException(format(\"Metrics %s are not found\", String.join(\", \", unfoundMetrics)));\n    }\n\n    return metrics;\n  }\n\n  private ComponentDto loadComponent(DbSession dbSession, SearchHistoryRequest request) {\n    String componentKey = request.getComponent();\n    String branch = request.getBranch();\n    String pullRequest = request.getPullRequest();\n    return componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, componentKey, branch, pullRequest);\n  }\n\n  static class SearchHistoryRequest {\n    private final String component;\n    private final String branch;\n    private final String pullRequest;\n    private final List<String> metrics;\n    private final String from;","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java#L250-L286","documentation":"SearchHistoryAction.searchMetrics validates that all up-to-date requested metrics exist before computing measure history, throwing IllegalArgumentException with the unfound metric keys. Unlike the component endpoints this surfaces as a 400 (bad request) rather than 404, but the cause is identical: requested metric keys absent from the metrics table.","triggerScenarios":"Calling api/measures/search_history with a metrics parameter containing one or more keys that selectByKeys does not resolve in the database.","commonSituations":"History dashboards referencing renamed/deleted metrics after upgrades; misspelled keys in CI scripts; custom metrics from a plugin that was removed so historical queries fail.","solutions":["Fix or drop the metric keys listed in the 'Metrics ... are not found' message.","List valid metrics via api/metrics/search and retry with confirmed keys.","Restore the plugin defining custom metrics before querying their history.","Wrap the call defensively in scripts and validate keys against the metrics list."],"exampleFix":"// before\nGET api/measures/search_history?component=my-app&metrics=ncol\n// after\nGET api/measures/search_history?component=my-app&metrics=ncloc","handlingStrategy":"validation","validationCode":"const known = new Set((await api.get('/api/metrics/search', {ps: 500})).metrics.map(m => m.key));\nconst missing = keys.filter(k => !known.has(k));\nif (missing.length) throw new Error('Metrics not found: ' + missing.join(', '));","typeGuard":null,"tryCatchPattern":"try { ... } catch (e) { if (String(e.message).includes('are not found')) { const missing = e.message.match(/Metrics (.*) are not found/)[1].split(', '); ... } throw e; }","preventionTips":["Fetch the metric list at script startup and intersect it with your requested keys.","After plugin removal, audit history queries that depended on its metrics."],"tags":["webapi","metrics","not-found","sonarqube"],"backgroundTag":"resource-not-found","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}