n8n-io/n8n · error · NodeOperationError

Failed to retrieve OAuth2 access token

Error message

Failed to retrieve OAuth2 access token

What it means

Catch-all in N8nOAuth2TokenCredential.getToken(): any error thrown after the access_token existence check (mostly from oAuthClient.credentials.getToken() during refresh/exchange) is wrapped as a NodeOperationError with message 'Failed to retrieve OAuth2 access token' and the original as cause. It exists to translate client-oauth2 library errors into a node-friendly message.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/llms/LmChatAzureOpenAi/credentials/N8nOAuth2TokenCredential.ts:47

				scopes: this.credential.scope?.split(' '),
				authentication: this.credential.authentication,
				authorizationUri: this.credential.authUrl,
				additionalBodyProperties: {
					resource: 'https://cognitiveservices.azure.com/',
				},
			});

			const token = await oAuthClient.credentials.getToken();
			const data = token.data as ClientOAuth2TokenData & {
				expires_on: number;
			};
			return {
				token: data.access_token,
				expiresOnTimestamp: data.expires_on,
			};
		} catch (error) {
			// Re-throw with better error message
			throw new NodeOperationError(this.node, 'Failed to retrieve OAuth2 access token', error);
		}
	}

	/**
	 * Gets the deployment details from the credential
	 */
	async getDeploymentDetails() {
		return {
			apiVersion: this.credential.apiVersion,
			endpoint: this.credential.endpoint,
			resourceName: this.credential.resourceName,
		};
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the wrapped cause for the Azure error (e.g. invalid_client, invalid_grant) and fix the underlying config.
  2. Reconnect the OAuth2 credential in n8n so a fresh refresh token is stored.
  3. Verify clientId/clientSecret against the Azure app registration and confirm the app is allowed to call Cognitive Services.
  4. Confirm accessTokenUrl and scope match the Azure cloud (public/gov/China) in use.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: ensure client secret and token URL are set
if (!credential.clientSecret || !credential.accessTokenUrl) {
  throw new Error('OAuth2 clientSecret and accessTokenUrl are required');
}

Type guard

const isClientOAuthError = (e: unknown): boolean =>
  /invalid_client|invalid_grant|unauthorized/i.test(e instanceof Error ? e.message : String(e));

Try / catch

try {
  return await oAuthClient.credentials.getToken();
} catch (e) {
  logger.warn(e);
  throw new NodeOperationError(node, 'Failed to retrieve OAuth2 access token', e as Error);
}

Prevention

When it happens

Trigger: The token exchange/refresh against accessTokenUrl fails — invalid client secret, wrong scope, expired refresh token, network error, Azure Entra endpoint returning an error body, or the additionalBodyProperties 'resource' value rejected by the tenant.

Common situations: Client secret rotated in Azure but not updated in n8n; scope missing 'https://cognitiveservices.azure.com/.default'; tenant admin conditional access blocking the token endpoint; accessTokenUrl wrong cloud (public vs gov); clock skew.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/0857e9840e6251cc. Report an issue: GitHub.