{"record":{"id":"d47a728475058c5e","repo":"ComposioHQ/composio","slug":"proxy-fetch-only-supports-get-post-put-delete","errorCode":null,"errorMessage":"proxy fetch only supports GET, POST, PUT, DELETE, PATCH.","messagePattern":"proxy fetch only supports GET, POST, PUT, DELETE, PATCH\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ts/packages/cli/src/services/run-helpers-runtime.ts","lineNumber":433,"sourceCode":"  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) => {\n      if (!headers.has(key)) headers.set(key, value);\n    });\n    return new Response(binaryResponse.body, {\n      status: result.status ?? binaryResponse.status,","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/cli/src/services/run-helpers-runtime.ts#L415-L451","documentation":"The proxy fetch layer only forwards GET, POST, PUT, DELETE, and PATCH (after uppercasing init.method; default GET). normalizeFetchInput rejects any other HTTP verb such as HEAD, OPTIONS, or custom methods.","triggerScenarios":"Calling proxy.fetch(url, { method: 'HEAD' }), { method: 'OPTIONS' }, or a lowercased verb that is still unsupported ('trace', 'connect').","commonSituations":"Health checks using HEAD, CORS preflight emulation with OPTIONS, or generic fetch wrappers that pass through arbitrary caller-supplied methods.","solutions":["Use one of GET/POST/PUT/DELETE/PATCH (case-insensitive)","For HEAD, issue a GET and ignore the body, or use a direct fetch outside the proxy","Validate the method against the allowlist before calling proxy.fetch when it comes from user input"],"exampleFix":"// before\nawait proxy.fetch(url, { method: 'HEAD' });\n// after\nawait proxy.fetch(url, { method: 'GET' }); // ignore response body if unneeded","handlingStrategy":"validation","validationCode":"const ALLOWED = ['GET','POST','PUT','DELETE','PATCH'];\nif (!ALLOWED.includes((method ?? 'GET').toUpperCase())) throw new RangeError(`method must be one of ${ALLOWED.join(',')}`);","typeGuard":"const isAllowedMethod = (m: string): m is 'GET'|'POST'|'PUT'|'DELETE'|'PATCH' => ['GET','POST','PUT','DELETE','PATCH'].includes(m.toUpperCase());","tryCatchPattern":null,"preventionTips":["Uppercase methods by convention","Avoid HEAD/OPTIONS through the proxy; use direct fetch"],"tags":["proxy","fetch","http-method","validation"],"backgroundTag":"unsupported-http-method","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}