hcengineering/platform · error · TypeError

Unsupported data type

Error message

Unsupported data type

What it means

The private-to-module toBuffer helper accepts only Buffer, string, or Node Readable streams before upload; any other value (e.g. Uint8Array, Blob, plain object, or a browser ReadableStream) falls into the else branch and a TypeError('Unsupported data type') is thrown. It surfaces from storageClient.put() and buffer().

Source

Thrown at foundations/core/packages/api-client/src/storage/client.ts:178

      method: 'DELETE',
      headers: { ...this.headers }
    })
  }
}

async function toBuffer (data: Buffer | string | Readable): Promise<Buffer> {
  if (Buffer.isBuffer(data)) {
    return data
  } else if (typeof data === 'string') {
    return Buffer.from(data)
  } else if (data instanceof Readable) {
    const chunks: Buffer[] = []
    for await (const chunk of data) {
      chunks.push(chunk)
    }
    return Buffer.concat(chunks as any)
  } else {
    throw new TypeError('Unsupported data type')
  }
}

async function wrappedFetch (url: string | URL, init?: RequestInit): Promise<Response> {
  let response: Response
  try {
    response = await fetch(url, init)
  } catch (error: any) {
    throw new NetworkError(`Network error ${error}`)
  }
  if (!response.ok) {
    const text = await response.text()
    if (response.status === 404) {
      throw new NotFoundError(text)
    } else {
      throw new StorageError(text)
    }
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Convert the value before calling put: Buffer.from(await new Response(webStream).arrayBuffer()) for web streams.
  2. Use fs.createReadStream(path) for files, or Buffer.from(uint8array) / Buffer.from(await blob.arrayBuffer()) for typed arrays and Blobs.
  3. Ensure TypeScript compiles with the declared put signature (Readable | Buffer | string) so mismatches are caught at build time.

Example fix

// before
const res = await fetch(fileUrl)
await storage.put(name, res.body, contentType) // TypeError: Unsupported data type
// after
const res = await fetch(fileUrl)
const buf = Buffer.from(await res.arrayBuffer())
await storage.put(name, buf, contentType)
Defensive patterns

Strategy: validation

Validate before calling

import { Readable } from 'stream'
function assertPutInput(data: unknown): asserts data is Buffer | string | Readable {
  if (!Buffer.isBuffer(data) && typeof data !== 'string' && !(data instanceof Readable)) {
    throw new TypeError(`put() needs Buffer | string | Readable, got ${data?.constructor?.name}`)
  }
}

Type guard

function isPutInput(data: unknown): data is Buffer | string | Readable {
  return Buffer.isBuffer(data) || typeof data === 'string' || data instanceof Readable
}

Try / catch

try {
  await storage.put(name, data, contentType)
} catch (e) {
  if (e instanceof TypeError && e.message === 'Unsupported data type') {
    // convert and retry once
    const buf = Buffer.from(await new Response(data as any).arrayBuffer())
    return storage.put(name, buf, contentType)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling storageClient.put(name, data, contentType) with data that is not Buffer/string/Readable — typically a Uint8Array, ArrayBuffer, Blob, or a web ReadableStream obtained from fetch response.body in a browser context.

Common situations: Passing response.body (a Web ReadableStream) directly to put(); passing a File/Blob from a browser file input; TypeScript types not enforced because the value came from an untyped API boundary; code written for a browser SDK reused in Node.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/aaf6db0cd861f00f. Report an issue: GitHub.