github/copilot-sdk · error · InvalidOperationException
No user input handler registered
Error message
No user input handler registered
What it means
HandleUserInputRequestAsync processes user-input requests sent by the Copilot CLI. It requires an application-registered user input handler (_userInputHandler); if none was registered when the CLI asks for user input, the SDK throws InvalidOperationException rather than silently returning an empty answer.
Solutions
- Register a user input handler on the session (the API that assigns _userInputHandler) before starting/continuing tasks.
- Implement the handler to surface the prompt to your UI/CLI and return a UserInputResponse.
- If interaction is impossible, ensure the agent flow avoids user-input-requiring tools, or catch the error and respond with a decline/failure to the request.
- Confirm the handler is registered on the same session instance that is running the task.
Example fix
// before
var session = new CopilotSession(...);
await session.SendAsync("deploy"); // throws on user input request
// after
var session = new CopilotSession(...);
session.RegisterUserInputHandler(async req => new UserInputResponse { Answer = Console.ReadLine() });
await session.SendAsync("deploy"); Defensive patterns
Strategy: validation
Validate before calling
if (!session.HasUserInputHandler)
session.RegisterUserInputHandler(req => Task.FromResult(new UserInputResponse { Answer = AskUser(req) })); Type guard
bool ready = session is { _userInputHandler: not null }; // prefer a public HasUserInputHandler check Try / catch
try { var resp = await session.HandleUserInputRequestAsync(request); }
catch (InvalidOperationException ex) when (ex.Message == "No user input handler registered")
{ return UserInputResponse.Decline("Interactive input unavailable"); } Prevention
- Register the user input handler before starting agent tasks
- Re-register handlers when recreating sessions
- Provide a headless default handler for test/CI runs
When it happens
Trigger: The host sends a UserInputRequest (e.g. the agent needs user confirmation/input) while the app never called the registration API that sets _userInputHandler, or the handler was registered on a different session instance.
Common situations: Running the SDK without wiring the user-input callback while the agent task requires interaction; forgetting to register handlers after recreating the session; interactive flows exercised in headless test runs.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Unsupported RuntimeConnection type
- CopilotClient was created with Mode =…
- CopilotClientOptions.Environment is not supported with…
- CopilotClientOptions.Telemetry is not supported with…
- CopilotClientOptions.WorkingDirectory is not supported with…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/cfe19244613c453c.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Session.cs:1682
if (result.Action == UIElicitationResponseAction.Accept
&& result.Content != null
&& result.Content.TryGetValue("value", out var val))
{
return val.ValueKind == JsonValueKind.String ? val.GetString() : val.ToString();
}
return null;
}
}
/// <summary>
/// Handles a user input request from the Copilot CLI.
/// </summary>
/// <param name="request">The user input request from the CLI.</param>
/// <returns>A task that resolves with the user's response.</returns>
internal async Task<UserInputResponse> HandleUserInputRequestAsync(UserInputRequest request)
{
var handler = _userInputHandler ?? throw new InvalidOperationException("No user input handler registered");
var invocation = new UserInputInvocation
{
SessionId = SessionId
};
var userInputTimestamp = Stopwatch.GetTimestamp();
var response = await handler(request, invocation);
LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null,
"CopilotSession.HandleUserInputRequestAsync dispatch. Elapsed={Elapsed}, SessionId={SessionId}",
userInputTimestamp,
SessionId);
return response;
}
/// <summary>
/// Handles an exit-plan-mode request from the Copilot CLI.
/// </summary>
/// <param name="request">The exit-plan-mode request from the CLI.</param>View on GitHub (pinned to cd8cf15dc3)