Skip to content

Fix: Response object mutation fails in ESM environments with node-fetch v3 #1429

@omarmciver

Description

@omarmciver

Problem

The generated Fetch client attempts to directly mutate the Response object by adding data and error properties. This fails in ESM environments using node-fetch v3 because Response objects are read-only.

Error

TypeError: Cannot set property data of #<Body> which has only a getter
    at /node_modules/.pnpm/@[email protected]/node_modules/@oars/v1.ts:1237:13

Environment

  • Node.js with ESM modules ("type": "module" in package.json)
  • node-fetch v3.x (ESM-only version)
  • swagger-typescript-api v13.0.23 (also confirmed in v13.2.13)

Root Cause

In templates/base/http-clients/fetch-http-client.ejs (lines 187-189), the code attempts to directly mutate the Response object:

const r = response as HttpResponse<T, E>;
r.data = (null as unknown) as T;
r.error = (null as unknown) as E;

This works in CommonJS environments but fails in ESM with node-fetch v3 where Response objects are truly read-only and cannot have new properties added.

Impact

Anyone migrating to ESM modules or using node-fetch v3 cannot use the generated Fetch client without workarounds.

Current Workaround

Users must wrap fetch with a Proxy to make Response properties writable:

const wrappedFetch = async (...args) => {
  const response = await fetch(...args);
  return new Proxy(response, {
    set(target, prop, value) {
      if (prop === 'data' || prop === 'error') {
        target[prop] = value;
        return true;
      }
      return Reflect.set(target, prop, value);
    },
    get(target, prop) {
      if (prop === 'data' || prop === 'error') {
        return target[prop];
      }
      const value = target[prop];
      if (typeof value === 'function') {
        return value.bind(target);
      }
      return value;
    }
  });
};

Proposed Solution

Create a wrapper object instead of mutating the Response directly. This maintains backward compatibility while supporting modern ESM environments.

I'll be submitting a PR with a fix shortly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions