ComposioHQ/composio · error · Error

proxy fetch requires a non-empty URL string or URL object.

Error message

proxy fetch requires a non-empty URL string or URL object.

What it means

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.

Source

Thrown at ts/packages/cli/src/services/run-helpers-runtime.ts:429

  if (typeof body === 'string' || typeof body === 'number' || typeof body === 'boolean')
    return body;
  if (typeof Blob !== 'undefined' && body instanceof Blob) return await body.text();
  if (body instanceof ArrayBuffer) return encodeBase64(new Uint8Array(body));
  if (ArrayBuffer.isView(body)) {
    return encodeBase64(new Uint8Array(body.buffer, body.byteOffset, body.byteLength));
  }
  return body;
};

const normalizeFetchInput = async (input: unknown, init: RequestInit = {}) => {
  if (typeof Request !== 'undefined' && input instanceof Request) {
    throw new Error(
      'proxy() does not support passing a Request instance yet. Pass a URL string and init instead.'
    );
  }
  const endpoint = input instanceof URL ? input.toString() : input;
  if (typeof endpoint !== 'string' || endpoint.trim().length === 0) {
    throw new Error('proxy fetch requires a non-empty URL string or URL object.');
  }
  const method = typeof init.method === 'string' ? init.method.toUpperCase() : 'GET';
  if (!['GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
    throw new Error('proxy fetch only supports GET, POST, PUT, DELETE, PATCH.');
  }
  return {
    endpoint: endpoint.trim(),
    method,
    parameters: normalizeFetchHeaders(init.headers),
    body: await normalizeFetchBody(init.body),
  };
};

const toProxyResponse = async (result: ProxyExecuteResponse) => {
  const headers = new Headers(result?.headers || {});
  if (result?.binary_data?.url) {
    const binaryResponse = await fetch(result.binary_data.url);
    binaryResponse.headers.forEach((value, key) => {

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Pass a concrete URL string: proxy.fetch('https://api.example.com/endpoint')
  2. Validate/derive the URL before calling: if (!url) throw ...
  3. Use new URL(...) to construct and validate the URL earlier, catching malformed input sooner

Example fix

// before
await proxy.fetch(`${process.env.API_BASE}/x`); // API_BASE unset -> '/x' or 'undefined/x'
// after
const base = process.env.API_BASE;
if (!base) throw new Error('API_BASE is required');
await proxy.fetch(`${base}/x`);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof url !== 'string' || url.trim().length === 0) throw new TypeError('URL string required');
await proxy.fetch(url);

Type guard

const isNonEmptyUrl = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;

Prevention

When it happens

Trigger: Calling proxy.fetch(''), proxy.fetch(undefined), proxy.fetch(42), or passing a URL object whose toString() is empty.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/9417720f81468bcb. Report an issue: GitHub.