github/copilot-sdk · error
no user input handler registered
Error message
no user input handler registered
What it means
handleUserInputRequest is invoked when the Copilot CLI asks the client for user input (e.g. a tool needs an interactive answer). If no handler was registered on the session via SetUserInputHandler (or the equivalent option), the SDK cannot answer the request and returns this error immediately. The error is returned to the CLI as the handler result, failing the pending operation.
Solutions
- Register a user input handler before sending prompts (SetUserInputHandler or the session option) that returns a UserInputResponse.
- If interactive prompts are undesired, use a non-interactive configuration or tool allowlist so the CLI never requests input.
- Upgrade the SDK/CLI pair if a new prompt type appeared that your registration path doesn't cover.
Example fix
// before
session, _ := client.CreateSession(ctx, nil)
session.SendPromptAndWait(ctx, prompt)
// after
session, _ := client.CreateSession(ctx, nil)
session.SetUserInputHandler(func(req copilot.UserInputRequest) (copilot.UserInputResponse, error) {
return copilot.UserInputResponse{Answer: "yes"}, nil
})
session.SendPromptAndWait(ctx, prompt) Defensive patterns
Strategy: validation
Validate before calling
if session.GetUserInputHandler() == nil {
session.SetUserInputHandler(func(req copilot.UserInputRequest) (copilot.UserInputResponse, error) {
return copilot.UserInputResponse{Answer: ""}, nil
})
} Try / catch
resp, err := session.SendPromptAndWait(ctx, prompt)
if err != nil && strings.Contains(err.Error(), "no user input handler registered") {
// register a handler and retry
} Prevention
- Always register a user input handler when creating interactive-capable sessions
- Use non-interactive tool configuration in headless/CI environments
- Wrap handler registration into your session factory helper so it's never forgotten
When it happens
Trigger: The CLI emits a user-input request during a turn (e.g. an interactive tool or clarification prompt) while Session has no user input handler registered.
Common situations: Running a session programmatically without registering OnUserInput/SetUserInputHandler while the model invokes an interactive tool; CLI version update introducing interactive prompts; headless/CI usage where a prompt is requested but never wired up.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- CopilotClient is in Mode = CopilotClientMode.Empty but the…
- User input requested but no handler registered
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
- gitHubToken and useLoggedInUser cannot be used with…
- sessionFs.initialCwd is required
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/d96d204f0473a83f.
Report an issue: GitHub.
Appendix: source
Thrown at go/session.go:673
s.userInputMux.Lock()
defer s.userInputMux.Unlock()
s.userInputHandler = handler
}
// getUserInputHandler returns the currently registered user input handler, or nil.
func (s *Session) getUserInputHandler() UserInputHandler {
s.userInputMux.RLock()
defer s.userInputMux.RUnlock()
return s.userInputHandler
}
// handleUserInputRequest handles a user input request from the Copilot CLI.
// This is an internal method called by the SDK when the CLI requests user input.
func (s *Session) handleUserInputRequest(request UserInputRequest) (UserInputResponse, error) {
handler := s.getUserInputHandler()
if handler == nil {
return UserInputResponse{}, fmt.Errorf("no user input handler registered")
}
invocation := UserInputInvocation{
SessionID: s.SessionID,
}
return handler(request, invocation)
}
func (s *Session) registerExitPlanModeHandler(handler ExitPlanModeRequestHandler) {
s.exitPlanModeMu.Lock()
defer s.exitPlanModeMu.Unlock()
s.exitPlanModeHandler = handler
}
func (s *Session) getExitPlanModeHandler() ExitPlanModeRequestHandler {
s.exitPlanModeMu.RLock()
defer s.exitPlanModeMu.RUnlock()View on GitHub (pinned to cd8cf15dc3)