Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: readableStream.tee is not a function (it is undefined) #6324

Closed
3 tasks done
umairm1alik opened this issue Jul 29, 2024 · 14 comments
Closed
3 tasks done

TypeError: readableStream.tee is not a function (it is undefined) #6324

umairm1alik opened this issue Jul 29, 2024 · 14 comments
Assignees
Labels
bug This issue is a bug. closed-for-staleness p2 This is a standard priority issue response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. workaround-available This issue has a work around available.

Comments

@umairm1alik
Copy link

umairm1alik commented Jul 29, 2024

Checkboxes for prior research

Describe the bug

I am trying to implement chunk approach to upload files in react native , if the file size is less then 5 mb its working fine other wise i am getting this error

SDK version number

"@aws-sdk/client-s3": "^3.592.0", "@aws-sdk/lib-storage": "^3.620.0",

Which JavaScript Runtime is this issue in?

React Native

Details of the browser/Node.js/ReactNative version

"react-native": "0.74.1",

Reproduction Steps

index.js

// import 'react-native-url-polyfill/auto';
// import 'react-native-get-random-values';
// import {ReadableStream} from 'web-streams-polyfill'
// globalThis.ReadableStream = ReadableStream;

import 'react-native-polyfill-globals/auto'
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

import {PutObjectCommand, S3Client, S3ClientConfig} from '@aws-sdk/client-s3';
import Config from 'react-native-config';
import RNFS from 'react-native-fs';
import {Buffer} from 'buffer';
import {handleS3Upload} from '../store/slices/homeSlice/homeSlice';
import {Audio, getFileSize, Image, Video} from 'react-native-compressor';
import {Upload} from '@aws-sdk/lib-storage';

const compressFileBasedOnType = async (
  filePath: string,
  contentType: string,
): Promise<string> => {
  let compressedFilePath = filePath;

  if (contentType.startsWith('image/')) {
    compressedFilePath = await Image.compress(filePath, {
      compressionMethod: 'auto',
    });
  } else if (contentType.startsWith('video/')) {
    compressedFilePath = await Video.compress(filePath, {
      compressionMethod: 'auto',
    });
  } else if (contentType.startsWith('audio/')) {
    compressedFilePath = await Audio.compress(filePath, {
      quality: 'medium',
    });
  } else {
    compressedFilePath = filePath;
  }

  return compressedFilePath;
};

interface UploadParams {
  filePath: string;
  fileName: string;
  contentType: string;
  dispatch?: (action: any) => void;
}

const createS3Client = (): S3Client => {
  const accessKeyId = Config.ACCESS_KEY_S3;
  const secretAccessKey = Config.SECRET_KEY_S3;

  if (!accessKeyId || !secretAccessKey) {
    throw new Error('AWS S3 credentials are not set');
  }

  const s3Config: S3ClientConfig = {
    region: Config.S3_BUCKET_REGION,
    credentials: {
      accessKeyId,
      secretAccessKey,
    },
  };

  return new S3Client(s3Config);
};

const uploadFileToS3 = async ({
  filePath,
  fileName,
  contentType,
  dispatch,
}: UploadParams): Promise<string> => {
  try {
    if (dispatch) {
      dispatch(handleS3Upload(true));
    }

    const compressedFilePath = await compressFileBasedOnType(
      filePath,
      contentType,
    );

    const fileContent = await RNFS.readFile(compressedFilePath, 'base64');
    const fileSize = await getFileSize(compressedFilePath);
    console.log('FileSize ====>', fileSize);
    const fileBuffer = Buffer.from(fileContent, 'base64');

    const s3Client = createS3Client();

    // const command = new PutObjectCommand({
    
    const upload = new Upload({
      client: s3Client,
      params: {
        Bucket: Config.BUCKET_NAME_S3,
        Key: fileName,
        Body: fileBuffer,
        ContentType: contentType,
      },

      partSize: 5 * 1024 * 1024, // 5 MB
      queueSize: 4, // 4 concurrent uploads
      leavePartsOnError: false, // Cleanup parts on error
    });

    upload.on('httpUploadProgress', progress => {
      console.log('Upload Progress:', progress);
      // You can also update your app's UI with the progress information here
    });

    await upload.done();
    if (dispatch) {
      dispatch(handleS3Upload(false));
    }

    const fileUrl = `https://${Config.BUCKET_NAME_S3}.s3.${Config.S3_BUCKET_REGION}.amazonaws.com/${fileName}`;
    console.log('fileUrl ======>', fileUrl);
    return fileUrl;
  } catch (error) {
    console.log('Error', error?.message, error);
    if (dispatch) {
      dispatch(handleS3Upload(false));
    }
    throw error;
  }
};

export default uploadFileToS3;

Observed Behavior

TypeError: readableStream.tee is not a function (it is undefined)

Expected Behavior

It should have to upload images , videos in chunk if its more then 5mb in size

Possible Solution

No response

Additional Information/Context

No response

@umairm1alik umairm1alik added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 29, 2024
@kuhe
Copy link
Contributor

kuhe commented Jul 29, 2024

Are you able to use a version of the ReadableStream polyfill that implements ReadableStream.prototype.tee()?

@umairm1alik
Copy link
Author

Before implementing Chunk with '@aws-sdk/lib-storage' I was uploading media files with aws-sdk/client-s3 and it was working.
Even now if the file size is smaller than 5 mb everything working properly.
But giving error for above 5 mb

@trivikr
Copy link
Member

trivikr commented Jul 29, 2024

As @kuhe asked, are you using a version of the ReadableStream polyfill that implements ReadableStream.prototype.tee()?

The JS SDK v3 required ReadableStream polyfill to work in react-native environment.
We added a recommendation to add web-streams-polyfill in the documentation in #6302

@trivikr trivikr added the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Jul 29, 2024
@LeandroTamola
Copy link

LeandroTamola commented Jul 29, 2024

I'm having the same issue with version "@aws-sdk/client-s3": "^3.620.1" and I'm already importing these in the index.js (root)

import "react-native-get-random-values";
import "react-native-url-polyfill/auto";
import "web-streams-polyfill/dist/polyfill";

@aBurmeseDev aBurmeseDev added investigating Issue is being investigated and/or work is in progress to resolve the issue. and removed needs-triage This issue or PR still needs to be triaged. labels Jul 29, 2024
@aBurmeseDev aBurmeseDev self-assigned this Jul 29, 2024
@aBurmeseDev
Copy link
Member

aBurmeseDev commented Jul 30, 2024

Hey all - thanks everyone for reporting. I was able to reproduce the error reported. For further analysis and potential resolution, I've prepared a couple test cases along with the versions of the relevant dependencies used during our testing.

  1. Test Case: ListObjects and PutObject with S3
  • install S3 client along with third-party libraries that provide polyfills for Web Streams API in React Native
"@aws-sdk/client-s3": "^3.620.1",
"web-streams-polyfill": "^4.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-url-polyfill": "^2.0.0"
  • import libraries
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import { ReadableStream } from "web-streams-polyfill";
import "web-streams-polyfill/dist/polyfill";
globalThis.ReadableStream = ReadableStream;
  • Error thrown on both ListObjects and PutObject: TypeError: readableStream.tee is not a function (it is undefined)
  • Tested different major versions of web-streams-polyfill and error remains.
  • Downgraded to "@aws-sdk/client-s3": "^3.574.0" and the call with successful.

npm i @aws-sdk/[email protected]


  1. Test Case: ListTables and PutItem with DynamoDB
"@aws-sdk/client-dynamodb": "^3.620.1",
"web-streams-polyfill": "^4.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-url-polyfill": "^2.0.0",

No error thrown for both operations.


If you're encountering the reported error with S3, please downgrade to @aws-sdk/[email protected] as a workaround, while we further look into it.

@umairm1alik
Copy link
Author

@aBurmeseDev thanks for the fast reply and solution.
Its working with @aws-sdk/[email protected]

@trivikr
Copy link
Member

trivikr commented Jul 30, 2024

  • Error thrown on both ListObjects and PutObject: TypeError: readableStream.tee is not a function (it is undefined)

If you're encountering the reported error with S3, please downgrade to @aws-sdk/[email protected] as a workaround

I'm not able to reproduce the issue with standard code samples in https://github.com/aws-samples/aws-sdk-js-tests for S3 ListObjects with v3.575.0

The ListObjects command is successful on iOS as shown in screenshot below

Screenshot screenshot-ios

I also downloaded local bundle, and verified that SDK version is v3.575.0.
Bundle for reference: index.bundle.js.txt


Patch file for repro: test-client-s3-list-objects.patch
To repro, just follow the README of https://github.com/aws-samples/aws-sdk-js-tests, and apply the patch using git apply.

On repro, the local bundle will be available on this URL.

@umairm1alik
Copy link
Author

umairm1alik commented Jul 31, 2024

If you're encountering the reported error with S3, please downgrade to @aws-sdk/[email protected] as a workaround, while we further look into it.

@aBurmeseDev I am still facing issues with this workaround sometimes it works fine and sometimes it still gives this error
[TypeError: readableStream.tee is not a function (it is undefined)]

@AhmedChebbiDRW
Copy link

Thank you , Its working with @aws-sdk/[email protected]

@aBurmeseDev aBurmeseDev added the p2 This is a standard priority issue label Jul 31, 2024
@aBurmeseDev
Copy link
Member

@umairm1alik - quick update here.

Initially, I was able to reproduce the error when using React Native with Expo. However, after starting a new React Native project without Expo, following the steps and code examples from the aws-sdk-js-tests, the issue was resolved.

This suggests that the root cause of the problem might be related to Expo itself or the way it integrates with the AWS SDK for JavaScript v3. To further investigate and identify the culprit, it would be helpful if you could share detailed steps to reproduce your workflow, including the dependencies you've installed.

Providing a step-by-step guide on how you set up your React Native project with Expo, the specific version of Expo you're using, and any other relevant dependencies or configurations, would assist in narrowing down the potential cause of the issue and determining if it's indeed related to Expo or if there are other factors at play.

@aBurmeseDev aBurmeseDev added response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. and removed response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. labels Aug 1, 2024
@therbta
Copy link

therbta commented Aug 1, 2024

Hey all - thanks everyone for reporting. I was able to reproduce the error reported. For further analysis and potential resolution, I've prepared a couple test cases along with the versions of the relevant dependencies used during our testing.

  1. Test Case: ListObjects and PutObject with S3
  • install S3 client along with third-party libraries that provide polyfills for Web Streams API in React Native
"@aws-sdk/client-s3": "^3.620.1",
"web-streams-polyfill": "^4.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-url-polyfill": "^2.0.0"
  • import libraries
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import { ReadableStream } from "web-streams-polyfill";
import "web-streams-polyfill/dist/polyfill";
globalThis.ReadableStream = ReadableStream;
  • Error thrown on both ListObjects and PutObject: TypeError: readableStream.tee is not a function (it is undefined)
  • Tested different major versions of web-streams-polyfill and error remains.
  • Downgraded to "@aws-sdk/client-s3": "^3.574.0" and the call with successful.

npm i @aws-sdk/[email protected]

  1. Test Case: ListTables and PutItem with DynamoDB
"@aws-sdk/client-dynamodb": "^3.620.1",
"web-streams-polyfill": "^4.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-url-polyfill": "^2.0.0",

No error thrown for both operations.

If you're encountering the reported error with S3, please downgrade to @aws-sdk/[email protected] as a workaround, while we further look into it.

Finally found a solution! Thank you so much!

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Aug 6, 2024
@aBurmeseDev aBurmeseDev added the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Aug 6, 2024
@kornicameister
Copy link

kornicameister commented Aug 8, 2024

I am seeing this in Lambda NodeJS 20 runtime.
I would like to avoid bundling AWS SDK manually though, any suggestions here?


What's funny is that file seems to be uploaded (yes, PutObject here) without a problem.

@umairm1alik
Copy link
Author

@aBurmeseDev I am using react native CLI not expo and my version is "react-native": "0.74.1"
at first, my issue was resolved with @aws-sdk/[email protected] but still, sometimes I was getting this issue then I updated to @aws-sdk/[email protected] and my issue was resolved.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Aug 9, 2024
@aBurmeseDev
Copy link
Member

Thanks for the update @umairm1alik!

It sounds like the error is intermittent for you, occurring with both @aws-sdk/[email protected] and @aws-sdk/[email protected]. This suggests that the issue may be caused by something outside of the AWS SDK itself.

As I mentioned earlier in my comment, I was able to reproduce the error when using Expo, but when I started a new plain React Native project without Expo, it worked as expected.

To further validate my theory, I attempted to reproduce the issue using the react-native reproducer provided by the React Native community. However, I was unable to reproduce the error following the instructions in the README for setting up and using the provided steps to start the Metro Server and the application.

Can you try reproducing the issue using the same reproducer and steps?
Here's patch file for repro ref: test-react-native-s3-list-objects.patch

@aBurmeseDev aBurmeseDev removed the investigating Issue is being investigated and/or work is in progress to resolve the issue. label Aug 15, 2024
@aBurmeseDev aBurmeseDev added the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Aug 15, 2024
@aBurmeseDev aBurmeseDev added the closing-soon This issue will automatically close in 4 days unless further comments are made. label Sep 26, 2024
@github-actions github-actions bot added closed-for-staleness and removed closing-soon This issue will automatically close in 4 days unless further comments are made. labels Sep 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. closed-for-staleness p2 This is a standard priority issue response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. workaround-available This issue has a work around available.
Projects
None yet
Development

No branches or pull requests

8 participants