FlowiseAI/Flowise · error · Error

Failed to refresh token: ${refreshResponse.status} ${refresh

Error message

Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}

What it means

Thrown when the internal OAuth2 refresh endpoint (POST /api/v1/oauth2-credential/refresh/<id>) responds with a non-2xx status. The message includes status code, status text, and the response body so the upstream refresh failure is visible. The provider itself (Google, Microsoft, GitHub, etc.) rejected the refresh attempt.

Source

Thrown at packages/components/src/utils.ts:1487

            try {
                // Import fetch dynamically to avoid issues
                const fetch = (await import('node-fetch')).default

                // Call the refresh API endpoint
                const refreshResponse = await fetch(
                    `${options.baseURL || 'http://localhost:3000'}/api/v1/oauth2-credential/refresh/${credentialId}`,
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        }
                    }
                )

                if (!refreshResponse.ok) {
                    const errorData = await refreshResponse.text()
                    throw new Error(`Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}`)
                }

                await refreshResponse.json()

                // Get the updated credential data
                const updatedCredentialData = await getCredentialData(credentialId, options)

                return updatedCredentialData
            } catch (error) {
                console.error('Failed to refresh access token:', error)
                throw new Error(
                    `Failed to refresh access token: ${
                        error instanceof Error ? error.message : 'Unknown error'
                    }. Please re-authorize the credential.`
                )
            }
        }
    }

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Read the embedded status + errorData: 400 invalid_grant means re-authorize; 401 means check client credentials.
  2. Confirm options.baseURL points at the reachable Flowise API (defaults to http://localhost:3000).
  3. If invalid_grant, re-authorize the OAuth2 credential — the refresh token is no longer usable.
  4. Verify the OAuth client ID/secret stored in Flowise match the provider console.
  5. Guard against concurrent refreshes (dedupe by credentialId) to avoid burning single-use refresh tokens.

Example fix

// before
if (!refreshResponse.ok) {
  const errorData = await refreshResponse.text()
  throw new Error(`Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}`)
}

// after — classify common provider errors for the caller
if (!refreshResponse.ok) {
  const errorData = await refreshResponse.text()
  let parsed: any = {}
  try { parsed = JSON.parse(errorData) } catch {}
  if (refreshResponse.status === 400 && parsed.error === 'invalid_grant') {
    throw new Error('Refresh token is invalid or expired — re-authorize the OAuth2 credential.')
  }
  throw new Error(`Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

function classifyRefreshFailure(status: number, body: string): 'invalid_grant' | 'client' | 'server' | 'unknown' {
  let p: any = {}
  try { p = JSON.parse(body) } catch {}
  if (status === 400 && p.error === 'invalid_grant') return 'invalid_grant'
  if (status === 401 || status === 400) return 'client'
  if (status >= 500) return 'server'
  return 'unknown'
}

Type guard

function isProviderGrantError(body: string): boolean {
  try { return JSON.parse(body)?.error === 'invalid_grant' } catch { return false }
}

Try / catch

if (!refreshResponse.ok) {
  const errorData = await refreshResponse.text()
  const kind = classifyRefreshFailure(refreshResponse.status, errorData)
  if (kind === 'invalid_grant') throw new Error('Refresh token invalid — re-authorize the credential.')
  throw new Error(`Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}`)
}

Prevention

When it happens

Trigger: Provider returns 400 invalid_grant (refresh token revoked, expired, or already used); 401 unauthorized_client (client secret changed); 400 invalid_client (misconfigured client ID/secret in Flowise); network error masqueraded as 5xx; refresh endpoint itself returned 404 because the credentialId doesn't exist.

Common situations: User revoked app access in the provider's account settings; client secret rotated in the provider console but not updated in Flowise; refresh token is single-use and was consumed by a concurrent request; the credential was deleted between the expiry check and the refresh call; Flowise server baseURL misconfigured so the request hits the wrong host.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/349279a01a7e7021. Report an issue: GitHub.