ToolJet/ToolJet · error · QueryError

Authorization Error

Error message

Authorization Error

What it means

Asana accessDetailsFrom() performs the OAuth token exchange inside try/catch. On any failure it throws QueryError 'Authorization Error' with error.response?.body || error.message and { error: error.message }. This covers the authorization-code → access-token exchange step failing.

Source

Thrown at marketplace/plugins/asana/lib/index.ts:78

      const result = JSON.parse(response.body);
      const authDetails: [string, string][] = [];

      if (result['access_token']) {
        authDetails.push(['access_token', result['access_token']]);
      }
      if (result['refresh_token']) {
        authDetails.push(['refresh_token', result['refresh_token']]);
      }
      if (result['expires_in']) {
        authDetails.push(['expires_in', result['expires_in'].toString()]);
      }
      if (result['token_type']) {
        authDetails.push(['token_type', result['token_type']]);
      }

      return authDetails;
    } catch (error) {
      throw new QueryError(
        'Authorization Error',
        error.response?.body || error.message,
        { error: error.message }
      );
    }
  }

  async refreshToken(
    sourceOptions: SourceOptions,
    _dataSourceId?: string,
    userId?: string,
    isAppPublic?: boolean
  ): Promise<{ access_token: string; refresh_token?: string }> {
    let refreshToken: string;
    if (sourceOptions.multiple_auth_enabled) {
      const currentToken = sourceOptions.tokenData?.find((t) =>
        isAppPublic && !userId ? true : t.user_id === userId
      );

View on GitHub (pinned to 20602a8e10)

Solutions

  1. Read error.response.body in the QueryError for Asana's specific OAuth error.
  2. Restart the OAuth flow to obtain a fresh authorization code.
  3. Ensure the redirect URI exactly matches the one registered in the Asana app.
  4. Confirm client_id/client_secret are correct for this environment.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: ensure the auth code is present and redirect URI matches the registered app before exchanging.
if (!authCode) throw new Error('Missing authorization code');
if (redirectUri !== registeredRedirectUri) throw new Error('Redirect URI mismatch');

Try / catch

try {
  return await asana.accessDetailsFrom(authCode, source_options);
} catch (e) {
  if (e?.message === 'Authorization Error') {
    const body = e?.data?.error;
    if (/invalid_grant|code/i.test(body)) promptReauthorize();
    else if (/redirect_uri/i.test(body)) notifyAdmin('Redirect URI mismatch in Asana app config.');
    else notifyUser('Asana authorization failed: ' + body);
  } else throw e;
}

Prevention

When it happens

Trigger: Invalid/expired authorization code. Redirect URI mismatch with the registered Asana app. Wrong client_secret/client_id. Code already exchanged (reuse). Network error hitting the Asana token endpoint.

Common situations: User retried the OAuth flow with a stale code. Redirect URI configured differently in the Asana app vs the datasource. Clock skew or token endpoint outage.

Related errors


AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13). Data as JSON: /api/errors/1c60e14fd285aa4d. Report an issue: GitHub.