{"record":{"id":"57ab53fcab3741cd","repo":"mastra-ai/mastra","slug":"invalid-api-key-or-insufficient-permissions","errorCode":null,"errorMessage":"invalid API key or insufficient permissions","messagePattern":"invalid API key or insufficient permissions","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"integrations/brightdata/src/client.ts","lineNumber":72,"sourceCode":"  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), effectiveTimeout);\n\n  try {\n    const response = await fetch(REQUEST_ENDPOINT, {\n      body: JSON.stringify(body),\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n        'Content-Type': 'application/json',\n      },\n      method: 'POST',\n      signal: controller.signal,\n    });\n\n    const responseText = await response.text();\n\n    if (!response.ok) {\n      if (response.status === 401 || response.status === 403) {\n        throw new Error('invalid API key or insufficient permissions');\n      }\n\n      if (response.status === 400) {\n        throw new Error(`bad request: ${responseText}`);\n      }\n\n      throw new Error(`request failed with status ${response.status}: ${responseText}`);\n    }\n\n    if (body.format === 'json') {\n      return responseText ? JSON.parse(responseText) : {};\n    }\n\n    return responseText;\n  } catch (error) {\n    if (error instanceof Error && error.name === 'AbortError') {\n      throw new Error(`Request timed out after ${effectiveTimeout}ms`);\n    }","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/integrations/brightdata/src/client.ts#L54-L90","documentation":"requestBrightData throws this when the Bright Data API responds with HTTP 401 or 403, meaning the API token was rejected or the account lacks permission for the requested zone/endpoint. The library treats both statuses as an authentication/authorization failure and aborts with this fixed message instead of the response body. It indicates the request reached Bright Data but credentials were not accepted.","triggerScenarios":"Any requestBrightData call (via client.search.google, etc.) where Bright Data returns status 401 or 403 — e.g. the Authorization header carried an invalid/expired/revoked token, the token lacks access to the configured serpZone/webUnlockerZone, or the account is blocked.","commonSituations":"BRIGHTDATA_API_TOKEN set to a placeholder or token from another account; token rotated/revoked while deploy env still holds the old value; zone deleted or renamed so the token's permissions no longer cover it; using a token type not permitted for the SERP API.","solutions":["Verify BRIGHTDATA_API_TOKEN (or the apiKey passed to getBrightDataClient) matches a valid token in the Bright Data dashboard.","Confirm the token has access to the configured zones (BRIGHTDATA_SERP_ZONE / BRIGHTDATA_WEB_UNLOCKER_ZONE or config serpZone/webUnlockerZone).","Test the token with a direct curl to the Bright Data endpoint to isolate library vs. credential issues.","If the token is valid but forbidden, check account status/billing and zone permissions in the Bright Data dashboard."],"exampleFix":"// before\nconst client = getBrightDataClient({ apiKey: 'my-password' });\n// after\nconst client = getBrightDataClient({ apiKey: process.env.BRIGHTDATA_API_TOKEN }); // real token from Bright Data dashboard","handlingStrategy":"try-catch","validationCode":"// before creating the client\nconst apiKey = configApiKey ?? process.env.BRIGHTDATA_API_TOKEN;\nif (!apiKey || apiKey.length < 10) {\n  throw new Error('BRIGHTDATA_API_TOKEN is missing or malformed');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = await client.search.google(query);\n} catch (err) {\n  if (err instanceof Error && err.message === 'invalid API key or insufficient permissions') {\n    // surface an auth-config alert; do NOT retry — fix the token/zones first\n    throw new Error('Check BRIGHTDATA_API_TOKEN and zone permissions');\n  }\n  throw err;\n}","preventionTips":["Store the token only in BRIGHTDATA_API_TOKEN and validate its presence at startup.","Rotate tokens centrally and update all environments simultaneously.","Grant the token access to every zone referenced by BRIGHTDATA_SERP_ZONE / BRIGHTDATA_WEB_UNLOCKER_ZONE.","Smoke-test credentials with a single search call in CI before deploy."],"tags":["auth","http-401","http-403","api-key","network"],"backgroundTag":"invalid-api-key","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}