diff --git a/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.test.tsx b/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.test.tsx
index 4c23c43e5..9b8761187 100644
--- a/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.test.tsx
+++ b/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.test.tsx
@@ -319,6 +319,42 @@ describe('EnterpriseSsoForm validation + save', () => {
});
});
+ it('does not log uncontrolled→controlled warnings when config resolves after load', async () => {
+ // Regression (#2095): the Select/Switch fields must be controlled from the
+ // first render. When `config` is undefined the seeded `data` is undefined,
+ // so `field.value` is undefined — without a defined fallback the controls
+ // mount uncontrolled, then warn once `config` hydrates them.
+ // Radix's `useControllableState` reports the transition via `console.warn`
+ // (React's native uncontrolled→controlled warning targets DOM inputs; these
+ // are button-based Radix controls), so spy on `warn`.
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
+ try {
+ const { rerender } = renderForm(undefined);
+
+ // Resolve the config — the form seeds its real values.
+ rerender(
+
+
+
+
+
+ ,
+ );
+
+ await screen.findByDisplayValue('Acme SSO');
+
+ const warned = warnSpy.mock.calls.some((call) =>
+ call.some(
+ (arg) =>
+ typeof arg === 'string' && /uncontrolled.*controlled/i.test(arg),
+ ),
+ );
+ expect(warned).toBe(false);
+ } finally {
+ warnSpy.mockRestore();
+ }
+ });
+
it('blocks the test action and does not call testConnection when invalid', async () => {
testConnMock.mockClear();
const { user } = renderForm(unconfigured);
diff --git a/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.tsx b/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.tsx
index 67155cbc0..5c0427e94 100644
--- a/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.tsx
+++ b/services/platform/app/features/settings/enterprise-sso/components/enterprise-sso-form.tsx
@@ -559,7 +559,10 @@ export function EnterpriseSsoForm({ organizationId, config }: Props) {
id="sso-protocol"
label={t('integrations.enterpriseSso.protocolLabel')}
description={t('integrations.enterpriseSso.protocolHelp')}
- value={field.value}
+ // Default to a defined value so the Select is controlled from
+ // the first render — `field.value` is undefined while `data`
+ // is still loading (avoids the uncontrolled→controlled warning).
+ value={field.value ?? ''}
onValueChange={(value) => {
const next = narrowStringUnion(
value,
@@ -670,7 +673,9 @@ export function EnterpriseSsoForm({ organizationId, config }: Props) {
name="pkce"
render={({ field }) => (
@@ -749,7 +754,10 @@ export function EnterpriseSsoForm({ organizationId, config }: Props) {