openapi-typescript icon indicating copy to clipboard operation
openapi-typescript copied to clipboard

AbortSignal is converted to plain object by unwrapRefs in Vue client

Open 9M6 opened this issue 2 weeks ago • 0 comments

openapi-typescript version

0.89.2

Node.js version

22

OS + version

macOS 15.7.3

Description

Client: Vue (@hey-api/client-nuxt or similar Vue-based client)

Problem

When passing an AbortSignal to an SSE endpoint, the request fails with:

TypeError: Failed to construct 'Request': Failed to read the 'signal' property from 'RequestInit': Failed to convert value to 'AbortSignal'.

Root Cause

The unwrapRefs function in sdk/client/utils.gen.ts recursively unwraps Vue refs by creating new plain objects and copying properties. When an AbortSignal is passed through this function, it gets converted to a plain object {} with the signal's properties copied over, but loses its prototype chain ([[Prototype]]: Object instead of [[Prototype]]: AbortSignal).

The browser's Request constructor then rejects this plain object because it's not a valid AbortSignal instance.

Current Code (problematic)

  export const unwrapRefs = <T>(value: T): UnwrapRefs<T> => {
    if (value === null || typeof value !== "object" || value instanceof Headers) {
      return (isRef(value) ? unref(value) : value) as UnwrapRefs<T>;
    }
    // ... clones object, stripping prototype
  };

Fix

Add AbortSignal to the early-return check, similar to how Headers is already handled:

  export const unwrapRefs = <T>(value: T): UnwrapRefs<T> => {
    if (value === null || typeof value !== "object" || value instanceof Headers || value instanceof AbortSignal) {
      return (isRef(value) ? unref(value) : value) as UnwrapRefs<T>;
    }
    // ...
  };

Reproduction

  1. Create an SSE endpoint using the generated SDK
  2. Pass an AbortController.signal to the request options
  3. The request fails immediately with the TypeError

Without passing a signal, it works because createSseClient falls back to new AbortController().signal which is created after unwrapRefs runs.

Expected result

AbortSignal to work

Required

  • [x] My OpenAPI schema is valid and passes the Redocly validator (npx @redocly/cli@latest lint)

Extra

9M6 avatar Dec 26 '25 11:12 9M6