RocketChat/Rocket.Chat · warning

Invalid OAuth client

Error message

Invalid OAuth client

What it means

useOAuthAppQuery's queryFn throws 'Invalid OAuth client' as a first guard when clientId is undefined — the hook cannot call GET /v1/oauth-apps.get without it. Because react-query executes queryFn as soon as the query mounts (unless disabled), an absent clientId turns into a failed query rather than a skipped one.

Source

Thrown at apps/meteor/client/views/oauth/hooks/useOAuthAppQuery.ts:19

import type { IOAuthApps } from '@rocket.chat/core-typings';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import type { UseQueryOptions } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';

type UseOAuthAppQueryOptions = Omit<
	UseQueryOptions<IOAuthApps, unknown, IOAuthApps, readonly ['oauth-app', { readonly clientId: string | undefined }]>,
	'queryKey' | 'queryFn'
>;

export const useOAuthAppQuery = (clientId: string | undefined, options?: UseOAuthAppQueryOptions) => {
	const getOAuthApp = useEndpoint('GET', '/v1/oauth-apps.get');

	return useQuery({
		queryKey: ['oauth-app', { clientId }] as const,

		queryFn: async () => {
			if (!clientId) {
				throw new Error('Invalid OAuth client');
			}

			const { oauthApp } = await getOAuthApp({ clientId });
			return {
				...oauthApp,
				_createdAt: new Date(oauthApp._createdAt),
				_updatedAt: new Date(oauthApp._updatedAt),
			};
		},
		...options,
	});
};

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Pass enabled: Boolean(clientId) through options so the query waits for the id.
  2. Fix the source of clientId (route param name, link generation) so it is present.
  3. Render a loading/empty state while clientId is undefined.

Example fix

// before
const { data } = useOAuthAppQuery(clientId);

// after
const { data } = useOAuthAppQuery(clientId, {
  enabled: Boolean(clientId),
});
Defensive patterns

Strategy: validation

Validate before calling

useOAuthAppQuery(clientId, {
  enabled: Boolean(clientId), // queryFn never runs with undefined
});

Type guard

const hasClientId = (v: string | undefined): v is string => Boolean(v && v.length > 0);

Prevention

When it happens

Trigger: Rendering the OAuth app admin/route that uses this hook without a clientId route param (bad link, missing parameter), or passing undefined during a parent's loading state while the query is still enabled.

Common situations: Deep links or bookmarks to /oauth/... missing the client id segment; refactors renaming the route param; component reused in contexts where the id arrives asynchronously.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/052406d7a54a33ff. Report an issue: GitHub.