jaydenseric / graphql-upload

Middleware and an Upload scalar to add support for GraphQL multipart requests (file uploads via queries and mutations) to various Node.js GraphQL servers.
https://npm.im/graphql-upload
MIT License
1.43k stars 131 forks source link

Error: A ReadStream cannot be created from a destroyed WriteStream. #283

Closed Froctnow closed 2 years ago

Froctnow commented 2 years ago

Hello, I have a resolver that receives files as input. Waiting for them to be received, then I try to create a stream, but I get an error: Error: A ReadStream cannot be created from a destroyed WriteStream. Resolver and function below. I am definitely not sending a response, the error falls exactly at the moment the createReadStream function is called.

  @UseGuards(AuthGuard)
  @Mutation(() => LocationEntity)
  async createLocation(
    @Args("createLocationData") createLocationData: LocationCreateInputModel,
    @Args({ name: "fileList", type: () => [GraphQLUpload] }) fileList: Promise<FileUpload>[],
    @CurrentUser() user: UserJwtDto,
  ) {
    const files = await this.locationService.waitUploadFiles(fileList);

    files[0].createReadStream();

    return await this.locationService.create(createLocationData, user.id, files);
  }
  async waitUploadFiles(fileList: Promise<FileUpload>[]) {
    const files: FileUpload[] = [];

    await doInParallel(fileList, file => file.then(res => files.push(res)));

    for (const file of files) {
      if (!["image/png", "image/webp", "image/jpeg"].includes(file.mimetype))
        throw new HttpException("Format file doesn't support. Use png, webp, jpeg", HttpStatus.BAD_REQUEST);
    }

    return files;
  }
jaydenseric commented 2 years ago

For issues like this, please share your Node.js and graphql-upload versions.

I'm confused by the logic in that resolver. You shouldn't await the promises to resolve for all files, then after attempt to read the stream of the first. Because files resolve and stream one at a time, one after another.

See in the multiple uploads example how the entire processing of each upload, including awaiting it's promise then promisifying the stream, happens in isolation:

Froctnow commented 2 years ago

I figured out the error, the problem was that the service was brought up under a user who does not have access to the file when you process it in proccessRequest. I don't get any error from the library about this, and the object becomes "destroyed". I don’t know how to test and catch this, I hope no one will encounter this.

sgentile commented 2 years ago

I get this when the filesystem is set to readonly