{"record":{"id":"4d4f613691564ab5","repo":"different-ai/openwork","slug":"t-providers-removal-unsupported","errorCode":null,"errorMessage":"t(\"providers.removal_unsupported\")","messagePattern":"t\\(\"providers\\.removal_unsupported\"\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/app/src/react-app/domains/connections/provider-auth/store.ts","lineNumber":1234,"sourceCode":"      assertNoClientError(result);\n      return;\n    }\n\n    const rawClient = (c as unknown as {\n      client?: { delete?: (options: { url: string }) => Promise<unknown> };\n    }).client;\n    if (rawClient?.delete) {\n      await rawClient.delete({ url: `/auth/${encodeURIComponent(providerId)}` });\n      return;\n    }\n\n    if (typeof authClient.set === \"function\") {\n      const result = await authClient.set({ providerID: providerId, auth: null });\n      assertNoClientError(result);\n      return;\n    }\n\n    throw new Error(t(\"providers.removal_unsupported\"));\n  };\n\n  const describeProviderError = (error: unknown, fallback: string) => {\n    const readString = (value: unknown, max = 700) => {\n      if (typeof value !== \"string\") return null;\n      const trimmed = value.trim();\n      if (!trimmed) return null;\n      if (trimmed.length <= max) return trimmed;\n      return `${trimmed.slice(0, Math.max(0, max - 3))}...`;\n    };\n\n    const records: Record<string, unknown>[] = [];\n    const root = error && typeof error === \"object\" ? (error as Record<string, unknown>) : null;\n    if (root) {\n      records.push(root);\n      if (root.data && typeof root.data === \"object\") {\n        records.push(root.data as Record<string, unknown>);\n      }","sourceCodeStart":1216,"sourceCodeEnd":1252,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/connections/provider-auth/store.ts#L1216-L1252","documentation":"removeProviderAuthCredentials tries three strategies to delete stored provider credentials from the connected opencode server: authClient.remove(), a raw DELETE /auth/:providerId, and finally authClient.set(providerID, auth: null). If the client object exposes none of these capabilities, the store concludes the connected server/client SDK version cannot remove credentials and throws this error. It is an API-surface/version-capability guard, not a server failure.","triggerScenarios":"Calling removeProviderAuthCredentials (via the store's provider-credential removal action) when options.client() returns a client whose auth object has no `remove` function, whose client has no `delete` method, and whose auth object has no `set` function.","commonSituations":"Connecting to an old opencode server or a mock/test client that predates the auth remove/set API; a stale pinned SDK client version; a custom client adapter that implements auth login but not logout; pointing the app at an incompatible/self-hosted server build.","solutions":["Upgrade the opencode server and client SDK so c.auth.remove or c.auth.set exists.","Verify options.client() returns the real SDK client, not a partial/stub object missing auth methods.","If removal is genuinely unsupported, clear the credential server-side manually (e.g. delete the auth entry from opencode's auth storage) and refresh the store.","In tests, use createTestStore with a client mock that implements auth.remove or auth.set."],"exampleFix":"// before: stub client without auth methods\nconst client = { auth: {} };\n// after: implement the removal surface\nconst client = { auth: { remove: async ({ providerID }) => ({ ok: true }) } };","handlingStrategy":"type-guard","validationCode":"const authClient = client.auth as { remove?: unknown; set?: unknown };\nconst canRemove = typeof authClient?.remove === \"function\" || typeof authClient?.set === \"function\";\nif (!canRemove) {\n  showToast(\"This server version cannot remove stored credentials; upgrade opencode.\");\n}","typeGuard":"function supportsCredentialRemoval(client: unknown): client is { auth: { set: (o: { providerID: string; auth: unknown }) => Promise<unknown> } } {\n  const c = client as { auth?: { set?: unknown } };\n  return typeof c?.auth?.set === \"function\";\n}","tryCatchPattern":"try {\n  await store.removeProviderCredentials(providerId);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"removal\")) {\n    showToast(\"Credential removal not supported by this server; clear it manually in opencode auth storage.\");\n  } else throw e;\n}","preventionTips":["Keep the opencode server and client SDK versions in lockstep.","Feature-detect auth.remove/auth.set before showing the 'Remove credentials' button.","In tests, use client mocks that implement the full auth surface (remove, set).","Document minimum server version requirements for credential management."],"tags":["auth","api-compatibility","client-version"],"backgroundTag":"api-endpoint-not-supported","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}