supabase/supabase · error · Error

App ID is required

Error message

App ID is required

What it means

Thrown by revokeAuthorizedApp when the id of the authorized OAuth app is missing before POSTing to /platform/organizations/{slug}/oauth/apps/{id}/revoke. The path requires a concrete app id to identify which authorization to revoke.

Source

Thrown at apps/studio/data/oauth/authorized-app-revoke-mutation.ts:14

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'

import { oauthAppKeys } from './keys'
import { handleError, post } from '@/data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from '@/types'

export type AuthorizedAppRevokeVariables = {
  id: string
  orgSlug: string
}

export async function revokeAuthorizedApp({ id, orgSlug: slug }: AuthorizedAppRevokeVariables) {
  if (!id) throw new Error('App ID is required')
  if (!slug) throw new Error('Organization slug is required')

  const { data, error } = await post('/platform/organizations/{slug}/oauth/apps/{id}/revoke', {
    params: { path: { slug, id } },
  })

  if (error) handleError(error)
  return data
}

type AuthorizedAppRevokeData = Awaited<ReturnType<typeof revokeAuthorizedApp>>

export const useAuthorizedAppRevokeMutation = ({
  onSuccess,
  onError,
  ...options
}: Omit<
  UseCustomMutationOptions<AuthorizedAppRevokeData, ResponseError, AuthorizedAppRevokeVariables>,

View on GitHub (pinned to beee91b9c2)

Solutions

  1. Disable the Revoke action on rows where id is missing.
  2. Pass the row's id explicitly from the mapped list item rather than a selected-state that may be null.
  3. Add an early return / toast in the click handler if !id.

Example fix

// before
const onRevoke = (app) => revoke({ id: app?.id, orgSlug })

// after
const onRevoke = (app) => {
  if (!app?.id) return
  revoke({ id: app.id, orgSlug })
}
Defensive patterns

Strategy: validation

Validate before calling

const onRevoke = (app?: { id?: string }) => {
  if (!app?.id) {
    toast.error('Cannot identify the app to revoke.')
    return
  }
  revoke({ id: app.id, orgSlug })
}

Type guard

const hasAppId = (
  v: { id?: string }
): v is { id: string } => typeof v.id === 'string' && v.id.length > 0

Try / catch

try {
  await revokeAsync({ id: id!, orgSlug })
} catch (e) {
  if (e instanceof Error && e.message === 'App ID is required') {
    toast.error('App not loaded yet. Refresh and try again.')
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: Revoke mutation fired from an account/integrations list row where the row's app id is undefined, or a programmatic revoke called without an id. The mutation destructures { id, orgSlug } and bails before the network call.

Common situations: List row key uses index instead of id and the row data is partially loaded; the revoke menu opens before the apps query returns; a stale ref holds an id that was cleared on unmount.

Related errors


AI-assisted analysis of supabase/supabase@beee91b9c2 (2026-08-12). Data as JSON: /api/errors/9b5455f8919c5eb6. Report an issue: GitHub.