graphql-upload: Error: A ReadStream cannot be created from a destroyed WriteStream.

Hi, I’ve got problem with reading contents from stream.

Either I get this error (👇) or writeStream hangs forever…

Error: A ReadStream cannot be created from a destroyed WriteStream.
    at WriteStream.createReadStream (/var/bb/node_modules/fs-capacitor/dist/index.js:174:19)
    at Object.createReadStream (/var/bb/node_modules/graphql-upload/lib/processRequest.js:297:28)

Example code:

class ImageStorageService {
  async uploadImage(upload: FileUpload): Promise<string> {
    const filename = `${cuid()}-${upload.filename}`;
    const tempFile = `${tmpdir()}/${filename}`;
    const readStream = upload.createReadStream();

    const writeStream = createWriteStream(tempFile);
    readStream.pipe(writeStream);

    // hangs forever, no finish event emitted
    const writePromise = new Promise((res) => {
      writeStream.on("open", () => {
        console.log("Stream opened");
      });
      writeStream.on("ready", () => {
        console.log("Stream ready");
      });
      writeStream.on("finish", () => {
        console.log("Stream finished");
        res();
      });
    });
    await writePromise;
   // ...
  }
}

Any ideas? Am I doing something wrong with streams?

Btw I had to use this fix to prevent maximum call stack size exceeded error.

  "resolutions": {
    "**/**/fs-capacitor": "^5.0.0",
    "**/graphql-upload": "^10.0.0"
  }

Node: v14.2.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 23 (4 by maintainers)

Most upvoted comments

I suspect this is behaving correctly and that your uploadImage function is likely being called after all your resolvers have returned.

Once the GraphQL operation has completed, the files backing these streams are flagged for deletion, and new read streams cannot be created from them. They will continue to serve existing read streams, though.

Essentially, it’s expected that you create all necessary streams before your resolver returns/resolves.

Hope you figured it out ok; we can reopen this issue if a specific graphql-upload bug is discovered.

@aseerkt in your example, stream is a readable stream, which is being piped into the writable stream returned by your call to createWriteStream(uploadPath). The finish event is something that is emitted by the latter, but you are listening for it on the former.

@koresar Damn you are right, I was using upload() instead of file(). Apologies for any confusion. Will definitely try it. Thanks 🙏