mastra-ai/mastra · error

bad request: ${responseText}

Error message

bad request: ${responseText}

What it means

requestBrightData throws this when Bright Data responds with HTTP 400, indicating the request payload was malformed or contained invalid parameters. The library includes the raw response body (responseText) in the message so the caller can see Bright Data's own complaint. This is a client-side request construction problem, not an auth or availability issue.

Source

Thrown at integrations/brightdata/src/client.ts:76

    const response = await fetch(REQUEST_ENDPOINT, {
      body: JSON.stringify(body),
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      method: 'POST',
      signal: controller.signal,
    });

    const responseText = await response.text();

    if (!response.ok) {
      if (response.status === 401 || response.status === 403) {
        throw new Error('invalid API key or insufficient permissions');
      }

      if (response.status === 400) {
        throw new Error(`bad request: ${responseText}`);
      }

      throw new Error(`request failed with status ${response.status}: ${responseText}`);
    }

    if (body.format === 'json') {
      return responseText ? JSON.parse(responseText) : {};
    }

    return responseText;
  } catch (error) {
    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error(`Request timed out after ${effectiveTimeout}ms`);
    }
    throw error;
  } finally {
    clearTimeout(timeoutId);
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read the responseText appended to the error — it contains Bright Data's specific reason for rejecting the request.
  2. Log and inspect the exact query and options passed to the search call; fix invalid values (empty query, bad params).
  3. Validate/normalize inputs (non-empty query, ISO language/country codes) before calling the client.
  4. Compare the generated request against the Bright Data API docs for the zone being used.

Example fix

// before
await client.search.google(userInput); // userInput may be ''
// after
const q = userInput.trim();
if (!q) throw new Error('search query must be non-empty');
await client.search.google(q);
Defensive patterns

Strategy: validation

Validate before calling

function assertValidSearchInput(query: string, options: SearchOptions = {}): void {
  if (typeof query !== 'string' || query.trim().length === 0) {
    throw new Error('search query must be a non-empty string');
  }
  if (query.length > 400) throw new Error('search query too long');
}

Type guard

function isNonEmptyQuery(q: unknown): q is string {
  return typeof q === 'string' && q.trim().length > 0;
}

Try / catch

try {
  const result = await client.search.google(query);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('bad request:')) {
    // log the Bright Data reason embedded in the message for debugging
    logger.warn({ reason: err.message }, 'brightdata rejected request');
    return null; // or rethrow after sanitizing inputs
  }
  throw err;
}

Prevention

When it happens

Trigger: Any requestBrightData call where Bright Data returns status 400 — e.g. empty or malformed query passed to client.search.google, invalid option values (bad country/language/zone params) that produce an invalid request URL or body.

Common situations: Passing an empty string as the search query; unsupported search parameters forwarded into the URL; a zone name with invalid characters; user-supplied input interpolated into the request without sanitization.

Understand the failure class

Background: BAD_REQUEST error code: request rejected as invalid (HTTP 400) - causes and fixes across libraries — this error's family across 8 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/af5b02f8b0fef830. Report an issue: GitHub.