QuantumNous/new-api · error · Error

Failed to fetch channel key

Error message

Failed to fetch channel key

What it means

Thrown by fetchChannelKey in the channel drawer when getChannelKey(channelId, proofToken) resolves with success=false. The backend message (e.g. key locked, proof verification required) replaces this i18n fallback; on success the key is revealed and 'Channel key unlocked' is toasted.

Source

Thrown at web/src/features/channels/components/drawers/channel-mutate-drawer.tsx:1370

            before: result.beforeCount,
            after: result.afterCount,
          }
        )
      )
    }
  }

  const fetchChannelKey = useCallback(
    async (proofToken?: string) => {
      if (!channelId) {
        throw new Error('Channel is not selected')
      }

      setIsChannelKeyLoading(true)
      try {
        const res = await getChannelKey(channelId, proofToken)
        if (!res.success) {
          throw new Error(res.message || t('Failed to fetch channel key'))
        }

        const keyValue = res.data?.key ?? ''
        setChannelKey(keyValue)
        toast.success(t('Channel key unlocked'))
        return res
      } finally {
        setIsChannelKeyLoading(false)
      }
    },
    [channelId, t]
  )

  const handleRevealKey = useCallback(async () => {
    if (!channelId) return

    try {
      await withVerification(fetchChannelKey, {

View on GitHub (pinned to e2c7aa7b10)

Solutions

  1. Read the toasted message — res.message carries the precise backend reason (proof required, forbidden, not found)
  2. If a proof token is required, complete the verification step first and pass the fresh proofToken to the call
  3. Confirm the logged-in account has permission to view channel keys (admin/root policy)
  4. Re-open the drawer from a valid channel row so channelId is current, and retry

Example fix

// before
const res = await getChannelKey(channelId, proofToken)
if (!res.success) {
  throw new Error(res.message || t('Failed to fetch channel key'))
}
// after - branch on proof-required instead of a generic failure
const res = await getChannelKey(channelId, proofToken)
if (!res.success) {
  if (res.message?.toLowerCase().includes('proof')) {
    openProofVerification()
    return
  }
  throw new Error(res.message || t('Failed to fetch channel key'))
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!channelId) throw new Error('Channel is not selected') // keep guard
// ensure a fresh proof token when the backend requires verification

Try / catch

setIsChannelKeyLoading(true)
try {
  const res = await getChannelKey(channelId, proofToken)
  if (!res.success) throw new Error(res.message || t('Failed to fetch channel key'))
  setChannelKey(res.data?.key ?? '')
  return res
} catch (error) {
  toast.error(error instanceof Error ? error.message : t('Failed to fetch channel key'))
  throw error // let proof-verification flows react
} finally {
  setIsChannelKeyLoading(false)
}

Prevention

When it happens

Trigger: Requesting the channel key when the server requires a passkey/WebAuthn proof token that is missing/invalid, when the admin lacks permission to view keys, when the channel id does not exist, or when the session has expired.

Common situations: Key-view permission policy enabled and the account lacks it; proof token expired so a fresh verification flow is needed; channel deleted concurrently; 401 after idle session.

Related errors


AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15). Data as JSON: /api/errors/82f38788e6064da3. Report an issue: GitHub.