{"record":{"id":"d0f58d9face97f22","repo":"usebruno/bruno","slug":"invalid-token-url-requestconfig-url","errorCode":null,"errorMessage":"Invalid token URL: ${requestConfig.url}","messagePattern":"Invalid token URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-requests/src/auth/oauth2-helper.ts","lineNumber":86,"sourceCode":" */\nconst applyAdditionalParameters = (requestConfig: RequestConfig, data: any, params: AdditionalParameter[] = []) => {\n  params.forEach((param) => {\n    if (!param.enabled || !param.name) {\n      return;\n    }\n\n    switch (param.sendIn) {\n      case 'headers':\n        requestConfig.headers[param.name] = param.value || '';\n        break;\n      case 'queryparams':\n        // For query params, add to URL\n        try {\n          const url = new URL(requestConfig.url);\n          url.searchParams.append(param.name, param.value || '');\n          requestConfig.url = url.href;\n        } catch (error) {\n          throw new Error(`Invalid token URL: ${requestConfig.url}`);\n        }\n        break;\n      case 'body':\n        // For body, add to data object\n        data[param.name] = param.value || '';\n        break;\n    }\n  });\n};\n\n/**\n * Safely parse JSON response data\n */\nconst safeParseJSONBuffer = (data: any) => {\n  try {\n    return JSON.parse(Buffer.isBuffer(data) ? data.toString() : data);\n  } catch {\n    return data;","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-requests/src/auth/oauth2-helper.ts#L68-L104","documentation":"Thrown by Bruno's OAuth2 helper (applyAdditionalParameters) when an additional parameter configured to be sent in queryparams cannot be appended because `new URL(requestConfig.url)` threw. The original URL parse error is swallowed and replaced with this message naming the offending URL.","triggerScenarios":"An OAuth2 token request whose Access Token URL is malformed (missing scheme, contains invalid characters, or is empty) and at least one additional parameter is set to sendIn: 'queryparams'.","commonSituations":"Token URL entered without the https:// scheme (e.g. 'example.com/oauth/token'); URL stored in a variable that resolved to undefined/empty; trailing space or stray character in the URL; a relative path used where an absolute URL is required.","solutions":["Set the OAuth2 Access Token URL to a fully-qualified absolute URL including scheme (https://...).","If the URL comes from a Bruno variable, confirm it is defined and non-empty in the active environment.","Move the parameter to headers or body if the URL is intentionally a relative path (the URL constructor is only invoked for the queryparams branch)."],"exampleFix":"// before — token URL has no scheme\nrequestConfig.url = 'example.com/oauth/token';\n// + an additional param with sendIn: 'queryparams'\n\n// after\nrequestConfig.url = 'https://example.com/oauth/token';","handlingStrategy":"validation","validationCode":"function assertAbsoluteUrl(u) {\n  try { new URL(u); } catch { throw new Error('Invalid token URL: ' + u); }\n}\nassertAbsoluteUrl(requestConfig.url);","typeGuard":"const isAbsoluteUrl = (v) => { try { new URL(v); return true; } catch { return false; } };","tryCatchPattern":"try { applyAdditionalParameters(requestConfig, data, params); }\ncatch (err) {\n  if (/Invalid token URL/.test(err.message)) {\n    requestConfig.url = 'https://' + requestConfig.url;\n  } else throw err;\n}","preventionTips":["Always include the scheme (https://) on the OAuth2 Access Token URL.","If a parameter does not need querystring placement, send it via headers or body to avoid the URL constructor path.","Pull URLs from environment variables that you validate once."],"tags":["bruno-requests","auth","oauth2","url","validation"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}