github / github/copilot-cli

Multiple-choice ask_user silently renders as a free-text prompt when trailing tool-call parameters leak into the preceding string argument

Đang mở
#4,817 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

triage
Ngôn ngữ chính
Shell
Star
11.2k
Fork
1.9k
Merge trung bình
14 giờ 16 phút
Pull request đã merge (30 ngày)
6

Mô tả

Describe the bug

An ask_user call that supplies choices sometimes renders as a plain free-text prompt ("Type your answer…") instead of the usual clickable option buttons — and the options themselves show up as a literal JSON array printed at the end of the question text.

The cause is upstream of any UI: the assistant emits Anthropic-style <parameter name="…"> markup inside a string argument, and the argument parser recovers only the first parameter. Every trailing parameter is silently absorbed into that first parameter's string value. Unlike #3765 (where the whole <invoke> block leaks as text and the tool never runs), here the tool call does execute — just with silently truncated arguments, so nothing surfaces as an error.

Verbatim from the session transcript (tool.execution_start), reformatted only for line breaks:

{
  "toolName": "ask_user",
  "arguments": {
    "question": "…Tests 244 → 247 passing, typecheck clean. Commit it?</question>\n<parameter name=\"choices\">[\"Commit (Recommended)\", \"Edit message\", \"Skip repo\", \"Cancel\"]"
  }
}

arguments has exactly one key. choices never arrives, so the client correctly renders a free-text prompt — it has no options to draw.

It is not ask_user-specific. The same shape corrupts ordinary tools, where the damage is worse because the call runs with wrong arguments and nobody notices. A grep call that lost its -n:

{ "-B": "30\">\n<parameter name=\"-n\">true", "output_mode": "content", "pattern": "latched" }
Affected version

Engine 1.0.84-4 (running inside the GitHub Copilot desktop app). Standalone CLI on PATH is 1.0.81-12. Occurrences in my logs span 2026-08-18 → 2026-09-11, so this is not new to one release.

Steps to reproduce the behavior

Not deterministic on demand — it depends on model output. What reliably produces it:

  1. Run a long session on claude-opus-5.
  2. Have the agent call ask_user with a choices array and a long question (every affected call was 643–944 characters; nothing shorter ever broke).
  3. Once one malformed call lands, every subsequent tool call of that kind in the session is malformed too — the model copies its own bad output from the transcript.
  4. Run /compact. The bad exemplar leaves the context window and calls go back to normal.

Step 3–4 is the strongest signal and is fully reproducible from logs — see the investigation block.

Expected behavior

Either the model never emits parameter markup inside a string value, or — more robustly — the argument parser refuses to accept a partial parse. A string value containing </param> / <parameter name="…"> is unambiguously a serialization failure, and the trailing parameters are trivially recoverable from it. Today it silently succeeds with dropped arguments, which is the worst of the three options.

Additional context

Suggested labels (I can't set them): area:tools, type: Bug.

Related: #3765 — same root family (parameter markup leaking), different failure mode: there the call is never executed; here it executes with silently truncated arguments.

Environment
Engine version   1.0.84-4  (GitHub Copilot desktop app)
CLI on PATH      1.0.81-12
OS               Microsoft Windows NT 10.0.26200.0
CPU arch         AMD64
Shell            PowerShell 7
Surface          desktop app, project session
Model            claude-opus-5 (long-context tier)
Frequency

Measured, not estimated — scanned every tool.execution_start event in my local session store:

Metric Value
Tool calls scanned 145,260
Calls with leaked parameter markup 18 (0.012%)
On claude-opus-5 17
On all other models combined 1 (claude-opus-4.8)

Tools affected: ask_user ×12, grep ×2, an ADO MCP tool ×2, a Bluebird MCP tool ×1, create ×1.

The global rate is low but misleading — it is heavily clustered. Within an affected session the rate is effectively 100% until a compaction clears it.

Extensions

Not tried with extensions disabled. Canvas extensions were loaded, but they cannot plausibly be involved: the corruption is present in the raw tool.execution_start event, before any client renders it.

Diagnostics available on request
  • Redacted events.jsonl excerpts for both affected sessions
  • The scan script used to produce the frequency table
In-depth investigation

The corruption is already present in the raw event, before anything renders it. The tool.execution_start record in the local session store shows arguments carrying a single question key. No client can draw option buttons from that — there are no options in the payload. So this is not a UI bug, and it will reproduce on any surface.

Why it's easy to miss. The stray </question> and <parameter name="choices"> don't show up on screen — only the bare ["Commit (Recommended)", …] array does. That makes it read as a formatting quirk rather than a dropped argument, which is why it took a log scan to find.

Contagion, bounded by compaction. This is the part I'd most like a maintainer to look at, because it turns a rare glitch into a session-wide outage.

Session A — 30 ask_user calls, all claude-opus-5:

calls  1–6    ok
               ← 5 compactions in 31 minutes (heavy context pressure)
calls  7–11   MALFORMED   (contiguous, ~26 h, no compaction in between)
               ← compaction
calls 12–30   ok          (19 consecutive clean calls)

The malformed run is bounded exactly by compaction events on both sides.

Session B — 7 ask_user calls, claude-opus-5, zero compactions for the life of the session (74% of a 1M context window): 7 of 7 malformed, starting with the very first one.

Reading: once one malformed call is in the context window it acts as a few-shot exemplar and the model reproduces its own broken shape indefinitely. Compaction rewrites the context, the exemplar disappears, and output returns to normal. Two sessions is a small sample, so I'd call this a strong inference rather than proven — but it matches both cases exactly and gives users a workaround (/compact, or switch model).

The existing guard isn't holding. The harness system prompt already carries a mitigation for this class — "when calling a tool whose parameter is an object, emit a real JSON object for that parameter. Never put XML or angle-bracket markup inside string values of a tool call." That instruction was in context for every one of the 18 malformed calls. A prompt-level guard can't win against the model's own prior output sitting in the same window; this needs a parser-level check.

Suggested fix, in priority order:

  1. Reject partial parses. If a decoded string argument contains </…> or <parameter name=, treat the tool call as malformed rather than passing along truncated arguments. Silent success is the real defect here.
  2. Recover them. </question>\n<parameter name="choices">["a","b"] is unambiguously parseable back into the intended arguments. A tolerant post-parse pass would fix the user-visible symptom outright.
  3. Break the contagion. If a malformed call is detected, avoid replaying its raw text into subsequent context — otherwise one bad call poisons the rest of the session.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu bằng cách lần theo trình phân tích cú pháp đối số tạo ra các sự kiện thô tool.execution_start, sử dụng các ví dụ không hợp lệ question-B làm đầu vào tái hiện. Kiểm tra cách markup tham số ở cuối bên trong các giá trị chuỗi đã giải mã được xử lý. Hoàn tất khi các lần phân tích từng phần không hợp lệ không còn âm thầm thực thi với các đối số bị loại bỏ và trình phân tích cú pháp có độ bao phủ cho các dạng đã báo cáo.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
shell
Lĩnh vực
cli, tooling
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
45/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.