Skip to content

Factory Droid questions show no options, split "Other" into a separate question, and answers are rejected as "cancelled by user" #21005

Closed

Description

@k00lagin

What happened

I answered all of Factory Droid's questions, but the agent treated it as if I had cancelled. Factory's options were never shown to me; I only saw the questions. And the custom answer had to be written in a separate question, while in ChatGPT and Claude you can write it right in the main question.

Diagnosis

The ACP adapter does not understand how Droid describes questions with fixed options, so it drops the options, splits "Other" into a separate question, and sends back an answer Droid rejects.

Droid 0.238.0 builds each single-select question as a titled enum plus a companion field for "Other" (reconstructed from Droid's bundled schema builder; the wire message was not captured):

"question_1": {
  "type": "string",
  "title": "Toolbar-color",
  "description": "How should the toolbar blend with the web content?",
  "oneOf": [
    { "const": "option_0", "title": "<option text>" },
    { "const": "option_1", "title": "<option text>" },
    { "const": "other", "title": "Other answer" }
  ]
},
"question_1_other": {
  "type": "string",
  "title": "Toolbar-color: Other answer",
  "description": "Enter your answer here if you select Other answer."
}

required lists only question_1. Multi-select uses type: "array" with items.anyOf of the same entries.

  • Options are lost. handleElicitation reads options only from enum and boolean. It ignores oneOf, so question_1 gets options: [].
  • "Other" becomes its own question. Every schema property becomes a separate question and required is ignored, so question_1_other is shown next to question_1. Clients already render an inline custom answer whenever allowCustomAnswer !== false (the OpenCode adapter uses this), so a separate field is not needed.
  • The answer is rejected. elicitationContent sends the free text as question_1. For questions with options, Droid accepts only option_N, or other with a non-empty question_N_other. Anything else makes it return cancelled: true, which its tool reports as Error: Tool execution cancelled by user. The user did not cancel.

I ran Droid's own response parser (extracted from the 0.238.0 binary) against the answers T3 saved in two threads (1 and 3 questions). Both reproduce cancelled: true. Replacing each question_N with "other" and keeping the text in question_N_other makes Droid accept every answer with the full text.

Possible fix, in the adapter only. OrchestrationV2UserInputQuestion already has options[].value, allowCustomAnswer, and required:

  1. Map oneOf: [{ const, title }] to options with label: title and value: const, and send the chosen value back.
  2. When a property has an other option and a matching <id>_other string field, fold both into one question with allowCustomAnswer: true, dropping the other option and the separate field. Send a custom answer back as <id>: "other" plus <id>_other: "<text>".
  3. Set required from the schema's required list.
  4. Add an adapter test with Droid's schema shape.

Free-text questions (no options) work today. Unchanged on main @ 13aa882.

Steps to reproduce

  1. Add Factory Droid as an ACP registry provider (Droid 0.238.0).
  2. Ask Droid something that makes it use its questionnaire tool with fixed options, e.g. "Ask me a multiple-choice question before you continue."
  3. The composer shows each question as two free-text questions, question_N and ": Other answer", with none of Droid's options.
  4. Answer and submit. T3 marks the request resolved; about 30–40 ms later Droid's tool fails with Error: Tool execution cancelled by user.

Version

0.1.1-nightly.20261017.3234 (desktop app, local server). Triage CLI: 0.1.0.

Environment

Windows 11 x64 (10.0.26200), T3 Code desktop nightly, Factory Droid 0.238.0 via ACP registry, Node v26.8.2

Evidence

# thread 1: user_input_request item
questions: [{ id: "question_1", options: [] }, { id: "question_1_other", options: [] }]
# 11:13:06.963Z runtime-request.updated
status: "resolved", answers: { question_1: "<text>", question_1_other: "<text>" }
# 11:13:06.997Z Droid tool result
output: "Error: Tool execution cancelled by user"

# thread 2: same shape with 3 questions (6 fields); resolved 20:16:51.308Z, tool failed 20:16:51.353Z

Related issues

#15743 touches the same adapter but covers Antigravity's missing elicitation capability and multi-select arrays, not single-select oneOf, the <id>_other field, or Droid's answer format. #9048 (closed) was a different elicitation mismatch.

Fix applied or workaround

Nothing was changed on the machine. Workaround: ask Droid to ask its questions in plain chat instead of its questionnaire tool.

Filed by

Claude Opus 5.5 via Factory Droid in T3 Code, following the t3 triage playbook; earlier investigation by GPT 6.1 Sol in Codex.

Activity

  1. juliusmarminge commented on Oct 17, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Thanks for the detailed write-up. This is the same Droid AskUser mapping bug that open draft PR #20417 fixes: it folds the oneOf choices and the question_N_other field into one question and sends custom text back as question_N: "other" plus question_N_other. I've linked the PR so this issue closes when it lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions