sipeed/picoclaw · error

No authorization code received

Error message

No authorization code received

What it means

In the OAuth callback handler, after the state check passes, a callback that carries no code parameter is rejected; the error message embeds the error query parameter (which may itself be empty). Per the OAuth2 spec the provider redirects with error=... (plus error_description) when authorization failed, so this signals the provider-side or user-side failure leg of the flow rather than a transport problem.

Source

Thrown at pkg/auth/oauth.go:204

func oauthCallbackRedirectURI(port int) string {
	return fmt.Sprintf("http://localhost:%d/auth/callback", port)
}

func oauthCallbackHandler(state string, resultCh chan<- callbackResult) http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/auth/callback", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Query().Get("state") != state {
			resultCh <- callbackResult{err: fmt.Errorf("state mismatch")}
			http.Error(w, "State mismatch", http.StatusBadRequest)
			return
		}

		code := r.URL.Query().Get("code")
		if code == "" {
			errMsg := r.URL.Query().Get("error")
			resultCh <- callbackResult{err: fmt.Errorf("no code received: %s", errMsg)}
			http.Error(w, "No authorization code received", http.StatusBadRequest)
			return
		}

		w.Header().Set("Content-Type", "text/html")
		fmt.Fprint(w, "<html><body><h2>Authentication successful!</h2><p>You can close this window.</p></body></html>")
		resultCh <- callbackResult{code: code}
	})
	return mux
}

func listenOAuthCallback(port int) (net.Listener, int, error) {
	listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
	if err != nil {
		return nil, 0, err
	}

	tcpAddr, ok := listener.Addr().(*net.TCPAddr)
	if !ok {

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Read the embedded error value in the message — access_denied means user denial, invalid_* points at client registration
  2. Verify client_id/secret and the exact redirect URI (scheme, port, path) registered with the provider
  3. Trim requested scopes to those the app registration actually grants, then retry login
  4. Retry the full flow from a fresh authorize URL
Defensive patterns

Strategy: retry

Try / catch

token, err := auth.Login(ctx)
if err != nil {
    msg := err.Error()
    switch {
    case strings.Contains(msg, "access_denied"):
        return errors.New("user denied consent — restart login and approve the requested scopes")
    case strings.Contains(msg, "invalid_scope"), strings.Contains(msg, "unauthorized_client"):
        return errors.New("provider rejected the request — verify client_id, scopes and redirect URI registration")
    }
    return err
}

Prevention

When it happens

Trigger: (1) User clicked Deny / cancelled consent → error=access_denied; (2) misconfigured client_id, requested scope, or redirect_uri → error=invalid_request / unauthorized_client / invalid_scope; (3) provider outage returning an error redirect; (4) an IdP that responds to the callback without either parameter (nonstandard).

Common situations: Scopes requested that the app registration does not have consent for; redirect URI registered in the provider portal not matching http://localhost:<port>/auth/callback; app in verification/pending state; user's admin policies blocking consent.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/525b1cbfa9adb20c. Report an issue: GitHub.