{"record":{"id":"b70b53758b9fcb27","repo":"different-ai/openwork","slug":"t-providers-oauth-method-required","errorCode":null,"errorMessage":"t(\"providers.oauth_method_required\")","messagePattern":"t\\(\"providers\\.oauth_method_required\"\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/app/src/react-app/domains/connections/provider-auth/store.ts","lineNumber":1559,"sourceCode":"  async function completeProviderAuthOAuth(\n    providerId: string,\n    methodIndex: number,\n    code?: string,\n  ) {\n    setStateField(\"providerAuthError\", null);\n    const c = options.client();\n    if (!c) {\n      throw new Error(t(\"providers.not_connected\"));\n    }\n\n    const resolved = providerId?.trim();\n    if (!resolved) {\n      throw new Error(t(\"providers.provider_id_required\"));\n    }\n    assertProviderAllowedByDesktopPolicy(resolved);\n\n    if (!Number.isInteger(methodIndex) || methodIndex < 0) {\n      throw new Error(t(\"providers.oauth_method_required\"));\n    }\n\n    const waitForProviderConnection = async (timeoutMs = 15000, pollMs = 2000) => {\n      const startedAt = Date.now();\n      while (Date.now() - startedAt < timeoutMs) {\n        try {\n          const updated = await refreshProviders({ dispose: true });\n          const connected = new Set(updated?.connected ?? []);\n          if (connected.has(resolved)) {\n            return true;\n          }\n        } catch {\n          // ignore and retry\n        }\n        await new Promise((resolve) => setTimeout(resolve, pollMs));\n      }\n      return false;\n    };","sourceCodeStart":1541,"sourceCodeEnd":1577,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/connections/provider-auth/store.ts#L1541-L1577","documentation":"createProviderAuthStore throws this when starting a provider OAuth flow with a methodIndex that is not a non-negative integer. The store indexes into the provider's list of OAuth sign-in methods, so a fractional, negative, or non-numeric index cannot select a method and the flow is aborted before any network call. It is a fail-fast input validation guard.","triggerScenarios":"Calling the OAuth start action with methodIndex = -1, 1.5, NaN, undefined, or a string like \"2\" from UI code or tests; passing a stale index after the provider's method list changed.","commonSituations":"Off-by-one or default -1 sentinel values; deriving the index from an untrusted URL param or query string; forgetting to update the index after a provider adds/removes an OAuth method.","solutions":["Pass the zero-based index of a valid OAuth method for the resolved provider.","Validate the index before calling: Number.isInteger(i) && i >= 0.","If the index came from saved state/URL, re-resolve it against the provider's current method list instead of reusing it.","For flows with a single method, pass 0 explicitly."],"exampleFix":"// before\nstore.startProviderOAuth(providerId, -1);\n// after\nconst methodIndex = provider.oauthMethods.findIndex((m) => m.id === wantedMethodId);\nif (methodIndex < 0) throw new Error(\"Unknown OAuth method\");\nstore.startProviderOAuth(providerId, methodIndex);","handlingStrategy":"validation","validationCode":"const idx = Number(methodIndex);\nif (!Number.isInteger(idx) || idx < 0) throw new Error(`Invalid OAuth method index: ${methodIndex}`);","typeGuard":"function isValidMethodIndex(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isInteger(v) && v >= 0;\n}","tryCatchPattern":"try {\n  store.startProviderOAuth(providerId, methodIndex);\n} catch (e) {\n  if (String((e as Error).message).includes(\"oauth_method_required\")) {\n    showInvalidMethodMessage();\n  }\n}","preventionTips":["Always pass a zero-based integer index resolved from the provider's method list","Never use -1 as a sentinel; use null/undefined and skip the call instead","Coerce URL/state-derived values with Number() and validate before use","Re-resolve indexes after provider method lists change"],"tags":["validation","oauth","input"],"backgroundTag":"invalid-argument","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}