moeru-ai/airi · error · Error

Failed to remove provider

Error message

Failed to remove provider

What it means

Thrown by deleteRemote when DELETE /api/v1/providers/:id returns non-2xx. Most commonly a 404 because the provider id no longer exists on the server (already deleted elsewhere or never synced), but auth failures and server errors collapse into the same message via the res.ok check.

Solutions

  1. Check the HTTP status; treat 404 as success (already gone) in callers where idempotent deletion is acceptable.
  2. Refresh the provider list (fetchRemote) and retry the delete against a confirmed-present id.
  3. Re-authenticate if 401/403.
  4. For 5xx, verify server logs for failing cascade deletes.

Example fix

// before
await providersService.deleteRemote(client, providerId)

// after - tolerate already-deleted providers
try {
  await providersService.deleteRemote(client, providerId)
}
catch (error) {
  // re-check existence; if it is gone, the goal is already met
  const providers = await providersService.fetchRemote(client)
  if (providers[providerId])
    throw error
}
Defensive patterns

Strategy: try-catch

Validate before calling

const providers = await providersService.fetchRemote(client, { abortSignal })
if (!providers[providerId]) {
  // already gone: nothing to delete
  return
}
await providersService.deleteRemote(client, providerId, { abortSignal })

Try / catch

try {
  await providersService.deleteRemote(client, providerId, { abortSignal })
}
catch (error) {
  const providers = await providersService.fetchRemote(client).catch(() => null)
  if (providers && !providers[providerId])
    return // 404-style: target already removed, treat as success
  toast.error(errorMessageFrom(error) ?? 'Failed to remove provider')
}

Prevention

When it happens

Trigger: Deleting a provider that was already removed from another tab/device (404); deleting before the initial providers fetch completed so the id was never server-side; auth expired (401); server error during cascading cleanup of provider-owned resources (500).

Common situations: Multi-tab/multi-device provider management racing deletions; UI list built from stale state; backend restarted with a reset database while the client kept old ids.

Related errors


AI-assisted analysis of moeru-ai/airi@0616eabd5b (2026-08-18). Data as JSON: /api/errors/dec8db727e7d6e2f. Report an issue: GitHub.

Appendix: source

Thrown at packages/stage-ui/src/services/inference-service-providers.ts:177

        validated: provider.status === 'configured',
        validationBypassed: provider.status === 'bypassed',
      },
    }, requestOptions(options))
    if (!res.ok)
      throw new Error('Failed to add provider')

    const item = await res.json()
    options?.abortSignal?.throwIfAborted()
    return normalize(item)
  }

  async function deleteRemote(client: InferenceServiceProvidersRemoteClient, providerId: string, options?: InferenceServiceProviderServiceOptions): Promise<void> {
    options?.abortSignal?.throwIfAborted()
    const res = await client.api.v1.providers[':id'].$delete({
      param: { id: providerId },
    }, requestOptions(options))
    if (!res.ok)
      throw new Error('Failed to remove provider')
    options?.abortSignal?.throwIfAborted()
  }

  async function patchConfigRemote(
    client: InferenceServiceProvidersRemoteClient,
    providerId: string,
    config: Record<string, unknown>,
    status: ProviderValidationStatus,
    options?: InferenceServiceProviderServiceOptions,
  ): Promise<InferenceServiceProvider> {
    options?.abortSignal?.throwIfAborted()
    const res = await client.api.v1.providers[':id'].$patch({
      param: { id: providerId },
      json: {
        config,
        validated: status === 'configured',
        validationBypassed: status === 'bypassed',
      },

View on GitHub (pinned to 0616eabd5b)