{"record":{"id":"2bfaae0dd52558fd","repo":"alibaba/arthas","slug":"32603-2bfaae","errorCode":"-32603","errorMessage":"Maximum task limit reached ({})","messagePattern":"Maximum task limit reached \\((.+?)\\)","errorType":"error_code","errorClass":"McpError","httpStatus":null,"severity":"error","filePath":"arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/InMemoryTaskStore.java","lineNumber":171,"sourceCode":"            return new InMemoryTaskStore<>(defaultTtl, defaultPollInterval, messageQueue, maxTasks);\n        }\n    }\n\n    private final Object createTaskLock = new Object();\n\n    private boolean isSessionValid(TaskEntry entry, String requestSessionId) {\n        if (requestSessionId == null) return true;\n        String taskSessionId = entry.sessionId();\n        if (taskSessionId == null || taskSessionId.isEmpty()) return true;\n        return requestSessionId.equals(taskSessionId);\n    }\n\n    @Override\n    public CompletableFuture<McpSchema.Task> createTask(CreateTaskOptions options) {\n        return CompletableFuture.supplyAsync(() -> {\n            synchronized (createTaskLock) {\n                if (tasks.size() >= maxTasks) {\n                    throw new CompletionException(\n                        McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)\n                            .message(\"Maximum task limit reached (\" + maxTasks + \")\")\n                            .build()\n                    );\n                }\n\n                String taskId = options.taskId() != null ? options.taskId() : UUID.randomUUID().toString();\n                String now = Instant.now().toString();\n                Long ttl = options.requestedTtl() != null ? options.requestedTtl() : defaultTtl;\n                Long pollInterval = options.pollInterval() != null ? options.pollInterval() : defaultPollInterval;\n                String sessionId = options.sessionId();\n\n                McpSchema.Task task = McpSchema.Task.builder()\n                    .taskId(taskId)\n                    .status(McpSchema.TaskStatus.WORKING)\n                    .createdAt(now)\n                    .lastUpdatedAt(now)\n                    .ttl(ttl)","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/InMemoryTaskStore.java#L153-L189","documentation":"Thrown by InMemoryTaskStore.createTask() when the number of stored tasks has reached maxTasks (default from the Builder). Creation is guarded by a synchronized createTaskLock and checks tasks.size() >= maxTasks; on overflow it throws a CompletionException wrapping a McpError with ErrorCodes.INTERNAL_ERROR (-32603). The limit caps memory use of the in-memory store.","triggerScenarios":"Creating tasks faster than they expire (TTL eviction) or reach terminal state; long TTLs accumulating many tasks; a client loop spawning tasks without waiting for completion; maxTasks configured too low for the workload.","commonSituations":"Load test or buggy client flooding task creation; low maxTasks default in a multi-tenant server; TTL set so high that evictions never free slots; tasks stuck in WORKING forever consuming slots.","solutions":["Raise maxTasks via InMemoryTaskStore.Builder().maxTasks(N) to match expected concurrency.","Lower the task TTL so completed/expired tasks free slots sooner.","Back-pressure the client: only create new tasks after prior ones finish or expire.","Ensure tasks actually reach terminal state so they can be evicted; switch to a persistent TaskStore for large scale."],"exampleFix":"// before\nInMemoryTaskStore.Builder<McpSchema.ServerTaskPayloadResult> b =\n    new InMemoryTaskStore.Builder<>();\nstore = b.build(); // default maxTasks too low\n\n// after\nstore = new InMemoryTaskStore.Builder<McpSchema.ServerTaskPayloadResult>()\n    .maxTasks(10_000)\n    .defaultTtl(Duration.ofMinutes(5).toMillis())\n    .build();","handlingStrategy":"retry","validationCode":"// Check remaining capacity before creating\nint remaining = maxTasks - store.size(); // if a size accessor exists\nif (remaining <= 0) {\n    // back-pressure: wait for tasks to expire or finish\n}","typeGuard":null,"tryCatchPattern":"// Retry creation after a short backoff once expired tasks free slots\ntry {\n    return store.createTask(options).join();\n} catch (CompletionException e) {\n    Throwable c = e.getCause();\n    if (c instanceof McpError me && me.getMessage().contains(\"Maximum task limit\")) {\n        Thread.sleep(pollInterval);\n        return store.createTask(options).join(); // retry once\n    }\n    throw e;\n}","preventionTips":["Set maxTasks to match expected peak concurrency.","Keep TTL short enough that tasks are evicted promptly.","Back-pressure clients so they create tasks at a sustainable rate.","Ensure tasks reach terminal state so slots free up."],"tags":["mcp","task","capacity","in-memory-store","java"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}