{"record":{"id":"9417720f81468bcb","repo":"ComposioHQ/composio","slug":"proxy-fetch-requires-a-non-empty-url-string-or-url","errorCode":null,"errorMessage":"proxy fetch requires a non-empty URL string or URL object.","messagePattern":"proxy fetch requires a non-empty URL string or URL object\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ts/packages/cli/src/services/run-helpers-runtime.ts","lineNumber":429,"sourceCode":"  if (typeof body === 'string' || typeof body === 'number' || typeof body === 'boolean')\n    return body;\n  if (typeof Blob !== 'undefined' && body instanceof Blob) return await body.text();\n  if (body instanceof ArrayBuffer) return encodeBase64(new Uint8Array(body));\n  if (ArrayBuffer.isView(body)) {\n    return encodeBase64(new Uint8Array(body.buffer, body.byteOffset, body.byteLength));\n  }\n  return body;\n};\n\nconst normalizeFetchInput = async (input: unknown, init: RequestInit = {}) => {\n  if (typeof Request !== 'undefined' && input instanceof Request) {\n    throw new Error(\n      'proxy() does not support passing a Request instance yet. Pass a URL string and init instead.'\n    );\n  }\n  const endpoint = input instanceof URL ? input.toString() : input;\n  if (typeof endpoint !== 'string' || endpoint.trim().length === 0) {\n    throw new Error('proxy fetch requires a non-empty URL string or URL object.');\n  }\n  const method = typeof init.method === 'string' ? init.method.toUpperCase() : 'GET';\n  if (!['GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {\n    throw new Error('proxy fetch only supports GET, POST, PUT, DELETE, PATCH.');\n  }\n  return {\n    endpoint: endpoint.trim(),\n    method,\n    parameters: normalizeFetchHeaders(init.headers),\n    body: await normalizeFetchBody(init.body),\n  };\n};\n\nconst toProxyResponse = async (result: ProxyExecuteResponse) => {\n  const headers = new Headers(result?.headers || {});\n  if (result?.binary_data?.url) {\n    const binaryResponse = await fetch(result.binary_data.url);\n    binaryResponse.headers.forEach((value, key) => {","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/cli/src/services/run-helpers-runtime.ts#L411-L447","documentation":"The proxied fetch requires the input to be a URL string or URL object that is non-empty after trimming. normalizeFetchInput throws when the endpoint resolves to undefined, a non-string, or blank text.","triggerScenarios":"Calling proxy.fetch(''), proxy.fetch(undefined), proxy.fetch(42), or passing a URL object whose toString() is empty.","commonSituations":"URL built from an unset env var producing '' or 'null', a template literal with an undefined interpolation, or passing an options object where a URL was expected.","solutions":["Pass a concrete URL string: proxy.fetch('https://api.example.com/endpoint')","Validate/derive the URL before calling: if (!url) throw ...","Use new URL(...) to construct and validate the URL earlier, catching malformed input sooner"],"exampleFix":"// before\nawait proxy.fetch(`${process.env.API_BASE}/x`); // API_BASE unset -> '/x' or 'undefined/x'\n// after\nconst base = process.env.API_BASE;\nif (!base) throw new Error('API_BASE is required');\nawait proxy.fetch(`${base}/x`);","handlingStrategy":"validation","validationCode":"if (typeof url !== 'string' || url.trim().length === 0) throw new TypeError('URL string required');\nawait proxy.fetch(url);","typeGuard":"const isNonEmptyUrl = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":null,"preventionTips":["new URL(base) throws on malformed input — use it to validate early","Never interpolate possibly-undefined env vars into URLs"],"tags":["proxy","fetch","url","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}