{"record":{"id":"68a1e32994951c93","repo":"pinpoint-apm/pinpoint","slug":"agentids-size-exceeds-max-limit-size-agentids-s","errorCode":null,"errorMessage":"agentIds size exceeds max limit. size: <agentIds.size()>, max: <MAX_AGENT_IDS>","messagePattern":"agentIds size exceeds max limit\\. size: <agentIds\\.size\\(\\)>, max: <MAX_AGENT_IDS>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":500,"severity":"error","filePath":"inspector-module/inspector-web/src/main/java/com/navercorp/pinpoint/inspector/web/service/DefaultAgentStatService.java","lineNumber":222,"sourceCode":"        }\n\n        return invokeList;\n    }\n\n    private QueryResult selectOneField(InspectorDataSearchKey inspectorDataSearchKey, MetricDefinition metricDefinition) {\n        Field field = metricDefinition.getFields().stream().findFirst().get();\n        CompletableFuture<List<DataPoint<Double>>> doubleFuture = agentStatDao.selectAgentStat(inspectorDataSearchKey, metricDefinition.getMetricName(), field);\n        return new QueryResult(doubleFuture, field);\n    }\n\n\n    @Override\n    public InspectorMetricGroupData selectAgentStatGroupedByAgentId(\n            String tenantId, String serviceName, String applicationName, List<String> agentIds,\n            String metricDefinitionId, TimeWindow timeWindow) {\n\n        if (agentIds.size() > MAX_AGENT_IDS) {\n            throw new IllegalArgumentException(\"agentIds size exceeds max limit. size: \" + agentIds.size() + \", max: \" + MAX_AGENT_IDS);\n        }\n\n        MetricDefinition metricDefinition = ymlInspectorManager.findElementOfBasicGroup(metricDefinitionId);\n\n        // One query per field (M queries) instead of N×M queries\n        List<BatchQueryResult> batchResults = selectAllByAgentIds(tenantId, serviceName, applicationName, agentIds, metricDefinition, timeWindow);\n\n        CompletableFuture<?>[] allFutures = batchResults.stream()\n                .map(BatchQueryResult::future)\n                .toArray(CompletableFuture[]::new);\n\n        try {\n            CompletableFuture.allOf(allFutures).get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new RuntimeException(e);\n        } catch (ExecutionException e) {\n            throw new RuntimeException(e.getCause());","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/inspector-module/inspector-web/src/main/java/com/navercorp/pinpoint/inspector/web/service/DefaultAgentStatService.java#L204-L240","documentation":"DefaultAgentStatService.selectAgentStatGroupedByAgentId throws IllegalArgumentException when the caller passes more than MAX_AGENT_IDS agent IDs in a single inspector metric query. The batched per-field query strategy fans out into collectors per agent, so an oversized agentId list would produce an unbounded query and result set; the service rejects it up front.","triggerScenarios":"Calling InspectorMetricController/service endpoints like /getAgentStatGroupedByAgentId with an agentIds parameter containing more than MAX_AGENT_IDS entries (e.g. selecting all agents of a very large application in one request).","commonSituations":"UI dashboards that select an entire application without pagination; scripted API calls that pass every agent ID of a large cluster; integration code that builds agentIds from a filtered-but-unbounded list after an agent count grew over time.","solutions":["Reduce the number of agentIds per request below MAX_AGENT_IDS (split into batches or paginate in the UI).","Filter agentIds by selected host/agent subset before calling selectAgentStatGroupedByAgentId.","Check MAX_AGENT_IDS in DefaultAgentStatService and, if genuinely needed, raise it consciously after assessing collector/storage load.","Catch IllegalArgumentException and surface a clear 'too many agents selected' message to the user."],"exampleFix":"// before\nList<String> agentIds = loadAllAgentIds(applicationName);\ninspectorStatService.selectAgentStatGroupedByAgentId(tenantId, serviceName, applicationName, agentIds, metricDefinitionId, timeWindow);\n\n// after\nList<String> agentIds = loadAllAgentIds(applicationName);\nfor (List<String> batch : Lists.partition(agentIds, MAX_AGENT_IDS)) {\n    inspectorStatService.selectAgentStatGroupedByAgentId(tenantId, serviceName, applicationName, batch, metricDefinitionId, timeWindow);\n}","handlingStrategy":"validation","validationCode":"if (agentIds.size() > MAX_AGENT_IDS) {\n    throw new IllegalArgumentException(\"agentIds size exceeds max limit. size: \" + agentIds.size() + \", max: \" + MAX_AGENT_IDS);\n}","typeGuard":null,"tryCatchPattern":"try {\n    data = service.selectAgentStatGroupedByAgentId(tenantId, serviceName, app, agentIds, metricDefId, timeWindow);\n} catch (IllegalArgumentException e) {\n    // fall back to batching\n}","preventionTips":["Partition agentId lists (e.g. Guava Lists.partition) before every call.","Enforce selection limits in the UI layer when picking agents of an application.","Log agent list sizes and alert before the limit is reached in production."],"tags":["argument-validation","batching","inspector","limit-exceeded"],"backgroundTag":"argument-out-of-range","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}