sipeed/picoclaw · warning

unsupported login method

Error message

unsupported login method

What it means

Returned as HTTP 400 by the default branch of the method switch in POST /api/oauth/login. It is a defensive fallback: every method accepted by isOAuthMethodSupported (browser, device_code, token) has an explicit case, so with a consistent build this branch is unreachable. Hitting it means the binary's method matrix and switch have diverged — someone added a method string to oauthProviderMethods without implementing its case (or vice versa in tests).

Source

Thrown at web/backend/api/oauth.go:317

			ExpiresAt:    now.Add(oauthBrowserFlowTTL),
			CodeVerifier: pkce.CodeVerifier,
			OAuthState:   state,
			RedirectURI:  redirectURI,
		}
		h.storeOAuthFlow(flow)

		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(map[string]any{
			"status":     "ok",
			"provider":   provider,
			"method":     method,
			"flow_id":    flow.ID,
			"auth_url":   authURL,
			"expires_at": flow.ExpiresAt.Format(time.RFC3339),
		})
		return
	default:
		http.Error(w, "unsupported login method", http.StatusBadRequest)
	}
}

func (h *Handler) handleGetOAuthFlow(w http.ResponseWriter, r *http.Request) {
	flowID := strings.TrimSpace(r.PathValue("id"))
	if flowID == "" {
		http.Error(w, "missing flow id", http.StatusBadRequest)
		return
	}

	flow, ok := h.getOAuthFlow(flowID)
	if !ok {
		http.Error(w, "flow not found", http.StatusNotFound)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(flowToResponse(flow))

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Rebuild/redeploy the backend from a consistent source tree so oauthProviderMethods and the switch agree.
  2. If you are extending the backend, add a switch case for every new method constant you add to the matrix.
  3. Add a unit test iterating oauthProviderMethods and asserting handleOAuthLogin returns non-400-default for each advertised method.

Example fix

// before: method advertised but not implemented
const (
    oauthMethodBrowser = "browser"
    oauthMethodDeviceCode = "device_code"
    oauthMethodToken = "token"
    oauthMethodSso = "sso" // added to matrix only -> 400 unsupported login method
)

// after: implement it or do not advertise it
switch method {
case oauthMethodToken: ...
case oauthMethodDeviceCode: ...
case oauthMethodBrowser: ...
case oauthMethodSso:
    // handle sso
}
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_METHODS = new Set(['browser', 'device_code', 'token']);
if (!KNOWN_METHODS.has(method)) throw new Error(`unknown login method ${method}`);

Type guard

function isKnownMethod(m) { return ['browser', 'device_code', 'token'].includes(m); }

Prevention

When it happens

Trigger: POST /api/oauth/login {"provider":"openai","method":"<new-method>"} where "<new-method>" was added to oauthProviderMethods in the deployed binary but the switch has no case for it. Not producible by any request against an unmodified build.

Common situations: Running a custom fork or unreleased branch that extends the login methods; stale cached build after pulling new code; a test double that injects an unsupported method.

Related errors


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