ToolJet/ToolJet · error · Error
Google OAuth "clientId" ${oauth_type === 'tooljet_app' ? 'en
Error message
Google OAuth "clientId" ${oauth_type === 'tooljet_app' ? 'environment variable' : 'config'} is missing What it means
The Google Calendar plugin's authUrl() reads the OAuth clientId from either the GOOGLE_CLIENT_ID environment variable (when oauth_type === 'tooljet_app') or from source_options.client_id.value. If neither resolves to a truthy string, this plain Error is thrown before any redirect URL is built. It is a configuration-time failure surfaced at the first attempt to start OAuth.
Source
Thrown at marketplace/plugins/googlecalendar/lib/index.ts:25
} from '@tooljet-marketplace/common';
import { SourceOptions, ConvertedFormat, QueryResult } from './types';
import got, { Headers, OptionsOfTextResponseBody } from 'got';
export default class GoogleCalendar implements QueryService {
authUrl(source_options: SourceOptions): string {
const host = process.env.TOOLJET_HOST;
const subpath = process.env.SUB_PATH;
const fullUrl = `${host}${subpath ? subpath : '/'}`;
const oauth_type = source_options.oauth_type.value;
let clientId: string;
if (oauth_type === 'tooljet_app') {
clientId = process.env.GOOGLE_CLIENT_ID;
} else {
clientId = source_options?.client_id?.value;
}
const scope = 'https://www.googleapis.com/auth/calendar';
if (!clientId) {
throw new Error(
`Google OAuth "clientId" ${oauth_type === 'tooljet_app' ? 'environment variable' : 'config'} is missing`
);
}
const encodedScope = this.encodeOAuthScope(scope);
const baseUrl =
'https://accounts.google.com/o/oauth2/v2/auth' +
`?response_type=code&client_id=${clientId}` +
`&redirect_uri=${fullUrl}oauth2/authorize`;
const authUrl = `${baseUrl}&scope=${encodedScope}&access_type=offline&prompt=consent`;
return authUrl;
}
private encodeOAuthScope(scope: string): string {
return encodeURIComponent(scope);
}
async run(View on GitHub (pinned to 20602a8e10)
Solutions
- If using tooljet_app mode: set GOOGLE_CLIENT_ID (and GOOGLE_CLIENT_SECRET) in the server environment and restart the process.
- If using custom mode: open the datasource configuration and supply client_id.value (and client_secret.value) from the Google Cloud Console credential.
- Verify the value is a non-empty string — an empty-string env var still fails the !clientId check.
- Confirm source_options.oauth_type.value is one of 'tooljet_app' or a custom mode so the correct branch resolves clientId.
Example fix
// before (env empty)
// .env: GOOGLE_CLIENT_ID=
// after
// .env:
GOOGLE_CLIENT_ID=123456-abc.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=yourSecret
// OR, in datasource config (custom mode):
source_options = {
oauth_type: { value: 'custom' },
client_id: { value: '123456-abc.apps.googleusercontent.com' },
client_secret: { value: 'yourSecret' }
}; Defensive patterns
Strategy: validation
Validate before calling
function resolveGoogleCalendarClientId(source_options, env = process.env) {
const oauth_type = source_options?.oauth_type?.value;
const clientId = oauth_type === 'tooljet_app'
? env.GOOGLE_CLIENT_ID
: source_options?.client_id?.value;
if (!clientId) {
throw new Error(
`Google OAuth clientId missing (mode=${oauth_type}). Set GOOGLE_CLIENT_ID env or client_id config.`
);
}
return clientId;
}
resolveGoogleCalendarClientId(source_options); Type guard
function hasGoogleCalendarClientId(source_options, env = process.env): boolean {
const oauth_type = source_options?.oauth_type?.value;
return oauth_type === 'tooljet_app'
? !!env.GOOGLE_CLIENT_ID
: !!source_options?.client_id?.value;
} Try / catch
try {
const url = plugin.authUrl(source_options);
} catch (e) {
if (/clientId.*missing/.test(e.message)) {
// prompt operator to set GOOGLE_CLIENT_ID or fill client_id config
}
throw e;
} Prevention
- On startup, log a warning if GOOGLE_CLIENT_ID is unset when tooljet_app mode is enabled.
- Document the env var in the datasource setup screen beside the oauth_type selector.
- Run a config self-check at deploy time that lists plugins with missing required env vars.
When it happens
Trigger: User selects 'tooljet_app' OAuth mode but the operator has not set GOOGLE_CLIENT_ID in the server env; OR user selects the custom ('config') mode but leaves the client_id field blank in the datasource config. Also triggered if oauth_type.value itself is undefined (the .value access would throw first, but a falsy clientId after that hits this branch).
Common situations: Fresh deploy of ToolJet without the GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET env vars set; misconfigured secret manager that injects an empty string; switching from tooljet_app to custom OAuth and forgetting to fill the new client_id field; copying source_options between environments and dropping the nested {value:"..."} structure.
Related errors
- HubSpot OAuth "clientId" ${oauth_type === 'tooljet_app' ? 'e
- HubSpot OAuth "clientSecret" ${oauth_type === 'tooljet_app'
- could not connect to Google Calendar
- access_token not found in the response
- Could not connect to Googles Calendar
AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13).
Data as JSON: /api/errors/1593fe8678a537bf.
Report an issue: GitHub.