question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Calling createReadStream() for uploaded file crashes in NodeJS 13

See original GitHub issue

Running in NodeJS 13.1.0:

const { createReadStream, filename } = await file // uploaded file
const stream = createReadStream()

Result:

RangeError: Maximum call stack size exceeded
        at _openReadFs (internal/fs/streams.js:1:1)        
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)
        at _openReadFs (internal/fs/streams.js:123:12)     
        at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
        at ReadStream.deprecated [as open] (internal/util.js:70:15)
        at ReadStream.open (D:\db-server\node_modules\fs-capacitor\lib\index.js:90:11)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:71
  • Comments:53 (9 by maintainers)

github_iconTop GitHub Comments

91reactions
abernixcommented, Jul 22, 2020

I know a lot of people are looking to be un-blocked here, so I want to offer this update and some instructions I put together as a suggestion, in hopes that it can be validated and that it works for those that need answers today, but also as a proof of concept for how we hope it will work in the future.

At a high level, while we believe that graphql-upload has provided tremendous value, we believe that the package itself stands really well on its own (see it’s own repository for the details, including the specification that supports it). It has been architected in a way where it can be added to a GraphQL server and doesn’t need to be baked into Apollo Server to function. Continuing along those lines, we think it will be able to serve the community if it is not closely coupled / bundled into Apollo Server as a direct dependency (and enabled by default).

In Apollo Server 3.0, we will not ship graphql-upload (or upload support) by default. While there are a number of ways to do uploads, the graphql-upload package is not the only way to do it. Some other suggestions have been outlined on our blog.. As for Apollo Server 2.x: due to (necessary) breaking changes in newer versions (see https://github.com/apollographql/apollo-server/pull/4039), the version of graphql-upload that exists today will not be updated further. (Semantically version speaking: the update would require a bump to v3, but we already plan on de-coupling it in v3.)

As for today / now: Anyone who wants to use a newer version of graphql-upload today, please try using the package’s own installation instructions, rather than using the baked-in Apollo Server version of graphql-upload.

I put these instructions together quickly and I believe they will work, but please help me correct any inaccuracies! 😄

  1. Switch from using apollo-server to one of the Apollo Server integration packages, like apollo-server-express.

    ❗ This step can be skipped if you’re already using apollo-server-koa, apollo-server-hapi, apollo-server-express, etc.!

    This is necessary because apollo-server (which uses apollo-server-express internally) doesn’t expose it’s HTTP server directly. If switching to the Express integration, this should be as simple as creating your own Express application:

    const express = require('express')
    const app = express();
    

    And then replacing the existing (roughly) server.listen(ListenOpts).then(OnListeningCallback) call with:

    server.applyMiddleware({ app });
    app.listen(ListenOpts, OnListeningCallback);
    

    …taking care to maintain the ListenOpts and OnListeningCallback as they were before, but in the new locations (note: not a Promise chain!)

    Note: some options which were normally provided on the ApolloServer constructor, like cors and onHealthCheck, will move to applyMiddleware’s options.

  2. Disable the upload support provided by the older graphql-upload version included in Apollo Server 2.x by setting uploads: false on the ApolloServer constructor’s “options”

    const server = new ApolloServer({
      typeDefs,
      resolvers,
      uploads: false, // Here!
    });
    
  3. Install the latest version of graphql-upload

    npm install graphql-upload@latest
    
  4. Import the necessary primitives from graphql-upload into the module where applyMiddleware is called

    const {
      GraphQLUpload, // The GraphQL "Upload" Scalar
      graphqlUploadExpress, // The Express middleware.
    } = require('graphql-upload');
    

    There is also a Koa middleware available. The processRequest function can be used for other implementations. The documentation is quite clear, but there are examples in our Apollo Server integration packages source code for how they’ve been implemented in Apollo Server 2.x.

  5. Add the Upload scalar to the schema by adding to the typeDefs SDL appropriately.

    scalar Upload
    
  6. Add a resolver for the Upload scalar

    const resolvers = {
      // Add this line to use the `GraphQLUpload` from `graphql-upload`.
      Upload: GraphQLUpload,
    
      /*
     ...
     Other resolvers remain the same.
     ...
      */
    
    },
    
  7. Add the graphql-upload middleware

    Add the graphqlUploadExpress middleware before calling into the ApolloServer instance’s applyMiddleware method with the app:

    const app = express(); // Existing.
    app.use(graphqlUploadExpress()); // New!
    server.applyMiddleware({ app }); // Existing.
    

    As noted above, there is also a Koa middleware and processRequest

And I think that should do it. I really hope this helps! While this does add a few lines of boiler-plate when you need uploads, it’s only a few lines.

If someone could try it out, it’d be greatly appreciated if it could be validated! Thanks!

56reactions
artoniocommented, Feb 21, 2020

This seems like a pretty serious bug. I’m surprised that it is still open…

Read more comments on GitHub >

github_iconTop Results From Across the Web

debugger crashes on createReadStream nodeJS
I am trying to create a read stream in order to upload a file from my client app (react) to the nodejs server....
Read more >
Stream | Node.js v19.3.0 Documentation
Data is buffered in Readable streams when the implementation calls stream.push(chunk) . If the consumer of the Stream does not call stream.read() ,...
Read more >
How to continuously read a file while the file is been writing
I want the user to be able to download a file while it is uploading. ... handling more exceptions (like, from calling createReadStream()...
Read more >
Discussion of Handling File Uploads with Apollo Server 2.0.
when i select file in frontend .the server crashed by it . can you help me with it. I have currently node js...
Read more >
Using Node to Read Really, Really Large Datasets (Pt 1)
readFile() wherein, the whole file is read into memory and then acted upon ... Node.js createReadStream() & readFile() Code Implementation.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found