mastra-ai/mastra · error
language must be a two-letter code (e.g. "en", "es")
Error message
language must be a two-letter code (e.g. "en", "es")
What it means
When client.search.google is called with a language option, getBrightDataClient validates it against /^[a-z]{2}$/i (a two-letter code). Anything else — full names like 'english', locales like 'en-US', or empty/whitespace values — throws this error before any network request is made. Valid codes are normalized to lowercase before building the request.
Source
Thrown at integrations/brightdata/src/client.ts:150
return body;
}
export function getBrightDataClient(config?: BrightDataClientOptions): BrightDataClient {
const apiKey = config?.apiKey ?? process.env.BRIGHTDATA_API_TOKEN;
if (!apiKey) {
throw new Error('Bright Data API token is required. Pass { apiKey } or set BRIGHTDATA_API_TOKEN env var.');
}
const timeout = config?.timeout;
const serpZone = config?.serpZone ?? process.env.BRIGHTDATA_SERP_ZONE ?? DEFAULT_SERP_ZONE;
const webUnlockerZone =
config?.webUnlockerZone ?? process.env.BRIGHTDATA_WEB_UNLOCKER_ZONE ?? DEFAULT_WEB_UNLOCKER_ZONE;
return {
search: {
google: async (query: string, options: SearchOptions = {}) => {
if (options.language && !/^[a-z]{2}$/i.test(options.language)) {
throw new Error('language must be a two-letter code (e.g. "en", "es")');
}
const normalizedOptions = options.language ? { ...options, language: options.language.toLowerCase() } : options;
const url = buildGoogleSearchUrl(query, normalizedOptions);
return requestBrightData(
apiKey,
toRequestBody(url, normalizedOptions.zone ?? serpZone, {
...normalizedOptions,
format: normalizedOptions.format ?? 'json',
method: 'GET',
}),
normalizedOptions.timeout ?? timeout,
);
},
},
scrapeUrl: async (url: string, options: RequestOptions = {}) => {
const response = await requestBrightData(View on GitHub (pinned to 75dd419e61)
Solutions
- Pass an ISO 639-1 two-letter code, e.g. { language: 'en' } or { language: 'es' }.
- Convert locale tags to their language subtag before calling: 'en-US' -> 'en'.
- Validate/normalize user-supplied language input at the boundary before invoking the client.
Example fix
// before
await client.search.google(q, { language: 'en-US' });
// after
await client.search.google(q, { language: 'en-US'.split('-')[0] }); // 'en' Defensive patterns
Strategy: validation
Validate before calling
function normalizeLanguage(input?: string): string | undefined {
if (!input) return undefined;
const code = input.split('-')[0].toLowerCase();
if (!/^[a-z]{2}$/.test(code)) {
throw new Error(`language must be an ISO 639-1 two-letter code, got: ${input}`);
}
return code;
}
// usage: client.search.google(q, { ...options, language: normalizeLanguage(options.language) }) Type guard
function isTwoLetterLanguage(v: unknown): v is string {
return typeof v === 'string' && /^[a-z]{2}$/.test(v);
} Prevention
- Always pass ISO 639-1 codes ('en', 'es'), never names or locale tags.
- Convert 'xx-YY' locale tags to their language subtag before calling.
- Validate language inputs at the UI/API boundary before they reach the client.
- Prefer omitting the language option when unknown instead of guessing a value.
When it happens
Trigger: Calling search.google(query, { language: 'english' }), { language: 'en-US' }, or any string that is not exactly two alphabetic characters.
Common situations: Passing a human-readable language name from UI state; passing an RFC 4646 locale tag ('en-US', 'pt-BR'); binding a select input that stores labels instead of ISO 639-1 codes.
Related errors
- Random walk steps must be greater than 0
- Restart probability must be between 0 and 1
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
- CursorSDKAgent resumeData.agentId must be a string when prov
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/74364eadbedc7724.
Report an issue: GitHub.