microsoft / microsoft/copilot-for-eclipse
[Bug] `conversation/templates` request never resolves after the first call, permanently hanging `ChatCompletionService.initConversationTemplates` (CompletableFuture#get with no timeout)
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 126
- Forks
- 60
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 5
Description
Environment
- OS: macOS (aarch64), Darwin 25.5.0
- Eclipse Version: 4.40.0.20260604-0652 (Eclipse IDE for Enterprise Java and Web Developers), LSP4E
0.19.12.202605060644, Java (Eclipse Adoptium)21.0.11 - Plugin Version:
0.20.0.202607100822(also reproduced on0.20.0.202607100750_nightly); GitHub Copilot Language Server1.509.5(Node.js22.22.3)
Describe the bug
After the very first conversation/templates LSP request succeeds, subsequent calls to the same method never receive a response from the GitHub Copilot Language Server, even though other request types sent in the same time window continue to resolve normally — so the LS process and JSON-RPC channel are not globally hung, only conversation/templates stops being answered after its first success.
Because ChatCompletionService.initConversationTemplates() calls CompletableFuture#get() with no timeout (and ModelService.fetchByokModels() has the identical pattern for listByokModels), the Eclipse Job worker thread that issued the request parks forever (WAITING on CompletableFuture$Signaller). Since Eclipse's Job.cancel() only flips an IProgressMonitor flag and cannot interrupt a thread already blocked inside CompletableFuture#get(), every time fetchAsync() fires again (e.g. on SKILL.md / *.prompt.md resource-change events) a new stuck worker thread accumulates and is never reclaimed. This has been observed to persist across Eclipse restarts — Eclipse's own shutdown handler logs "Job found still running after platform shutdown" for the same stuck job on repeated sessions.
Traced via decompilation of the plugin/LSP4E jars, the call chain has no timeout anywhere:
ChatCompletionService.initConversationTemplates()
-> this.lsConnection.listConversationTemplates(workspaceFolders).get() // NO TIMEOUT
CopilotLanguageServerConnection.listConversationTemplates()
-> this.languageServerWrapper.execute(fn) // LSP4E
LanguageServerWrapper.execute() -> executeImpl() -> getInitializedServer() -> start()
// none of these apply any timeout to the eventual server response
Two compounding issues:
- Server-side: whatever handles
conversation/templatesinside the Copilot Language Server appears to stop responding to that method after the first successful call in a session (root cause not visible from the client side — needs LS-side investigation; looks like a debounce/memoization/in-flight-promise bug keyed by request method rather than by request id). - Client-side: because
.get()has no timeout anywhere in the call chain, and job cancellation cannot interrupt a thread already parked in.get(), a single unanswered request permanently strands a worker thread. Repeated triggers (e.g. many resource-change events in a multi-root workspace) accumulate multiple stuck threads per session.
To Reproduce
- Open Eclipse with a multi-root workspace containing custom
SKILL.md/*.prompt.mdfiles across several projects (this appears to increase the chance offetchAsync()firing multiple times in quick succession during startup). - Sign in to Copilot and let the workspace finish loading/indexing.
- Enable LSP4E tracing (
Preferences > Language Servers > Logs, enable "Log to File" for server idcom.microsoft.copilot.eclipse.ls) to capture the raw JSON-RPC traffic. - Observe in the trace log that the first
conversation/templatesrequest/response pair succeeds:--> {"jsonrpc":"2.0","id":"4","method":"conversation/templates","params":{"workspaceFolders":[...]}} <-- {"jsonrpc":"2.0","id":"4","result":[{"id":"tests", ...}, ...]} // full template list returned correctly - Watch for later
conversation/templatesrequests (fired again byfetchAsync()), e.g.:
These never receive a matching response, while other concurrent request ids in the same window (e.g.--> {"jsonrpc":"2.0","id":"24","method":"conversation/templates","params":{...}} // never answered --> {"jsonrpc":"2.0","id":"32","method":"conversation/templates","params":{...}} // never answeredid=23,id=17,id=14,id=31) resolve normally. - Take a Java thread dump of the Eclipse process; a
Worker-N: Refresh slash commands servicethread is permanentlyWAITINGinsideChatCompletionService.initConversationTemplates:"Worker-14: Refresh slash commands service" #102 prio=5 ... elapsed=247.05s ... waiting on condition java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(Native Method) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:221) at java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1864) at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3780) at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3725) at java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1898) at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2072) at com.microsoft.copilot.eclipse.ui.chat.services.ChatCompletionService.initConversationTemplates(ChatCompletionService.java:126) at com.microsoft.copilot.eclipse.ui.chat.services.ChatCompletionService$1.run(ChatCompletionService.java:99) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Expected behavior
conversation/templates should keep responding on every call for the lifetime of the session (or at minimum, the client should time out and recover instead of hanging a worker thread forever). Slash-command / template data in the chat panel should keep refreshing instead of silently freezin
g after the first successful fetch, and ChatCompletionService.isTempaltesReady() should not get permanently stuck once this happens.
Screenshots
N/A — this is a backend/threading hang with no visible UI error. Happy to attach the full sanitized LSP trace log and a Java thread dump on request.
Additional context
- The exact same hang has recurred across multiple Eclipse restarts in our environment: at previous sessions' shutdown, Eclipse's own job manager logged the same stuck stack trace for
ChatCompletionService$1, and — via the identicallsConnection.xxx().get()pattern with no timeout — for
ModelService$1(ModelService.fetchByokModels,ModelService.java:220) as well:!ENTRY org.eclipse.core.jobs 2 2 2026-07-24 06:29:30.048 !MESSAGE Job found still running after platform shutdown. ...: com.microsoft.copilot.eclipse.ui.chat.services.ChatCompletionService$1 RUNNING at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2072) at com.microsoft.copilot.eclipse.ui.chat.services.ChatCompletionService.initConversationTemplates(ChatCompletionService.java:126) at com.microsoft.copilot.eclipse.ui.chat.services.ChatCompletionService$1.run(ChatCompletionService.java:99) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) !ENTRY org.eclipse.core.jobs 2 2 2026-07-24 06:29:30.048 !MESSAGE Job found still running after platform shutdown. ...: com.microsoft.copilot.eclipse.ui.chat.services.ModelService$1 RUNNING at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2072) at com.microsoft.copilot.eclipse.ui.chat.services.ModelService.fetchByokModels(ModelService.java:220) at com.microsoft.copilot.eclipse.ui.chat.services.ModelService$1.run(ModelService.java:176) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) - Suggested fixes:
- Investigate why the Copilot Language Server only answers the first
conversation/templatesrequest per session and silently drops subsequent ones. - On the extension side, add a bounded timeout (e.g.
.get(30, TimeUnit.SECONDS)) to the blocking calls inChatCompletionService.initConversationTemplatesandModelService.fetchByokModels(and audit other similarlsConnection.xxx().get()call sites), logging/reporting a timeout ins
tead of hanging forever. - Make
fetchAsync()'s job cancellation actually propagate to the in-flightCompletableFuture(e.g. keep a reference and call.cancel(true)on it) instead of only cancelling theIProgressMonitor, which has no effect on a thread already inside.get().
- Investigate why the Copilot Language Server only answers the first
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ChatCompletionService.initConversationTemplates and ModelService.fetchByokModels, then trace the conversation/templates requests using the LSP4E log and the provided thread-dump stack. Reproduce the unanswered request and repeated resource-change triggers; done means the request path no longer leaves Eclipse workers blocked indefinitely and template/model refreshes recover when a response is missing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100