tldraw/tldraw · error · Error

Could not stream object ${obj.Key}

Error message

Could not stream object ${obj.Key}

What it means

After confirming Body exists, the script requires Body.transformToWebStream to pipe the R2 object into tar extract. Older AWS SDK v2 style bodies (Readable streams) lack transformToWebStream; the guard catches that incompatibility before attempting iteration.

Source

Thrown at internal/scripts/deploy-dotcom.ts:1063

		objectsToFetch.map((k) => k.Key)
	)
	for (const obj of objectsToFetch) {
		const { Body } = await R2.send(
			new GetObjectCommand({
				Bucket: R2_BUCKET,
				Key: obj.Key,
			})
		)
		if (!Body) {
			throw new Error(`Could not fetch object ${obj.Key}`)
		}
		// pipe into untar
		// `keep-existing` is important here because we don't want to overwrite the new assets
		// if they have the same name as the old assets becuase they will have different sentry debugIds
		// and it will mess up the inline source viewer on sentry errors.
		const out = tar.x({ cwd: assetsDir, 'keep-existing': true })
		if (!Body?.transformToWebStream) {
			throw new Error(`Could not stream object ${obj.Key}`)
		}
		for await (const chunk of Body.transformToWebStream() as any as AsyncIterable<Uint8Array>) {
			out.write(Buffer.from(chunk.buffer))
		}
		out.end()
	}
}

main().catch(async (err) => {
	// don't notify discord on preview builds
	if (env.TLDRAW_ENV !== 'preview') {
		await discord.message(`${Discord.AT_TEAM_MENTION} Deploy failed: ${err.stack}`, {
			always: true,
		})
	}
	console.error(err)
	process.exit(1)
})

View on GitHub (pinned to b31086b447)

Solutions

  1. Ensure @aws-sdk/client-s3 v3 (modular) is installed at the version declared in the workspace.
  2. If using an alternate S3 client, wrap its stream: `Readable.toWeb(Body)` to produce a web stream.
  3. Upgrade Node to >=22.12 (repo requirement) for native web stream support.

Example fix

// before
if (!Body?.transformToWebStream) {
  throw new Error(`Could not stream object ${obj.Key}`)
}
// after (fall back to Node stream conversion)
const webStream = Body.transformToWebStream
  ? Body.transformToWebStream()
  : Readable.toWeb(Body)
Defensive patterns

Strategy: fallback

Validate before calling

// Detect stream capability before iterating
if (typeof Body?.transformToWebStream !== 'function' && typeof Body?.pipe !== 'function') {
  throw new Error(`Object body has no usable stream interface: ${obj.Key}`)
}

Type guard

function isWebStreamBody(Body: unknown): Body is { transformToWebStream: () => ReadableStream } {
  return Boolean(Body && typeof (Body as any).transformToWebStream === 'function')
}

Prevention

When it happens

Trigger: Using a stream type that doesn't expose transformToWebStream (AWS SDK v2, or a mocked/test double); SDK downgrade or polyfill removing the method.

Common situations: @aws-sdk/client-s3 major version mismatch; running the script under a Node version or runtime without web streams; third-party S3-compatible client returning a Node Readable.

Related errors


AI-assisted analysis of tldraw/tldraw@b31086b447 (2026-08-12). Data as JSON: /api/errors/1048d3b9681d7077. Report an issue: GitHub.