Meteor-files: addFile returns this error on server code: UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

Created on 23 Apr 2020  路  6Comments  路  Source: veliovgroup/Meteor-Files

Hi all,
Trying to run _addFile_ on a meteor method (server) gives me this error:

UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

I have run the _addFile_ method using async/await; without async/await; and with
Async (meteorhacks:async). I always get same error.

Note: the document is saved on the collection in mongo. But the error occurs and the
method does not return normally to the client.

This is my collection:

import { FilesCollection } from 'meteor/ostrio:files';
import SimpleSchema from 'simpl-schema';

const mySchema = {
  ...FilesCollection.schema,
};

export const FluentReports = new FilesCollection({
  collectionName: 'fluentReports',
  allowClientCode: false, // Disallow remove files from Client
  debug: true
});

FluentReports.collection.attachSchema(new SimpleSchema(mySchema));

This is my meteor method:

Meteor.methods({
'requerimientos.reports.general_4'() {

    const user = Meteor.user();
    const fileName = `req.report.general.${user._id}.pdf`; 
    let finalPath = path.join(process.env.PWD, `/.temp`, fileName);
    finalPath = finalPath.replace(/\\/g, "/");

    let response = null;
    response = Async.runSync(function(done) {
        Promise.resolve(
            FluentReports.addFile(finalPath, { 
                    fileName: fileName,
                    type: 'pdf',
                    fileId: new Mongo.ObjectID()._str,
                    meta: {owner: this.userId, createdAt: new Date()}
            })
        )
        .then(function(result) { done(null, result); })
        .catch(function (err) { done(err, null); })
        .done();
    });

    if (response.error) {
        console.log(`An error occurred: ${response.error.message}`)
    }

    return { 
            error: false, 
            message: "Ok, el reporte ha sido agregado a meteor-files.", 
            result: response
           }  
}})
  • Version of Meteor-Files you're experiencing this issue: ostrio:[email protected]

  • Version of Meteor you're experiencing this issue: [email protected]

  • Where this issue appears? OS (Mac/Win/Linux)? Browser name and its version?
    Windows 10 / Chrome: Version 81.0.4044.113 (Official Build) (64-bit)

  • Is it Client or Server issue?
    Server - _addFile_ on meteor method

    This is what is in the console after the error occurs:

  I20200423-16:47:47.561(-4)? [FilesCollection] [addFile(C:/requerimientos/.temp/req.report.general.67Qjx32kS7bmhWcfp.pdf)]
W20200423-16:47:52.497(-4)? (STDERR) (node:12008) UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded
W20200423-16:47:52.498(-4)? (STDERR)     at Function.[Symbol.hasInstance] (<anonymous>)
W20200423-16:47:52.499(-4)? (STDERR)     at Object.EJSON.isBinary (packages/ejson/ejson.js:426:54)
W20200423-16:47:52.499(-4)? (STDERR)     at Object.EJSON.clone (packages/ejson/ejson.js:571:13)
W20200423-16:47:52.499(-4)? (STDERR)     at packages/ejson/ejson.js:600:22
W20200423-16:47:52.500(-4)? (STDERR)     at Array.forEach (<anonymous>)
W20200423-16:47:52.500(-4)? (STDERR)     at Object.EJSON.clone (packages/ejson/ejson.js:599:13)
W20200423-16:47:52.501(-4)? (STDERR)     at packages/ejson/ejson.js:600:22
W20200423-16:47:52.501(-4)? (STDERR)     at Array.forEach (<anonymous>)
W20200423-16:47:52.501(-4)? (STDERR)     at Object.EJSON.clone (packages/ejson/ejson.js:599:13)
W20200423-16:47:52.502(-4)? (STDERR)     at packages/ejson/ejson.js:600:22
W20200423-16:47:52.502(-4)? (STDERR)     at Array.forEach (<anonymous>)
W20200423-16:47:52.502(-4)? (STDERR)     at Object.EJSON.clone (packages/ejson/ejson.js:599:13)
W20200423-16:47:52.503(-4)? (STDERR)     at packages/ejson/ejson.js:600:22
W20200423-16:47:52.503(-4)? (STDERR)     at Array.forEach (<anonymous>)
W20200423-16:47:52.504(-4)? (STDERR)     at Object.EJSON.clone (packages/ejson/ejson.js:599:13)
W20200423-16:47:52.504(-4)? (STDERR)     at packages/ejson/ejson.js:600:22
W20200423-16:47:52.504(-4)? (STDERR) (node:12008) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)
I20200423-16:47:52.858(-4)? [FilesCollection] [addFile]: req.report.general.67Qjx32kS7bmhWcfp.pdf -> fluentReports

Many thanks ...

.addFile() question

Most helpful comment

Hi @dr-dimitru , everything is working fine right now. Many thanks for all your help.
The final (condensed) code follows:

1) This is how I coded the meteor method:

'requerimientos.reports.general'() {
       ... ... 
        var addFileSync = Meteor.wrapAsync(FluentReports.addFile, FluentReports);

        let result; 

        try { 
            result = addFileSync(finalPath, { fileName: fileName,
                                              type: 'pdf',
                                              fileId: new Mongo.ObjectID()._str,
                                              meta: {owner: this.userId, createdAt: new Date()}
                                            }); 
        } catch(error) { 
            return { 
                    error: true, 
                    message: `Error: some error has ocurrend: ${error.message}`, 
                }
        }
        return { 
                    error: false, 
                    result: result
                } 
    }

2) This is how I call the method from client:

const getReportGeneral2 = () => {
    Meteor.call('requerimientos.reports.general', (error, result) => {

        if (error || result.error) {
            // report your error 
            return;
        }

        Meteor.subscribe('meteor.files.by.id', result.result._id, () => {

            const report = FluentReports.findOne(result.result._id);    

            if (!report) { 
                // report your error ... 
            } else { 
                const link = ` <a href="${report.link()}?download=true" download="${report.name}" target="_blank">${report.name}$</a> `;
               // show link so user can download the file 
            }
        });
    });
}

3) This is the needed subscription:

import { Meteor } from 'meteor/meteor';
import { FluentReports } from '/imports/api/collections/meteor_files/fluentReports'; 

Meteor.publish("meteor.files.by.id", function (fileId) {
    return FluentReports.collection.find({ _id: fileId });
})

Many thanks again. I'm just beginning to know the library; however I can sense its very well done. And very useful.

All 6 comments

I believe (after looking on logs) EJSON.clone just go crazy in the infinity loop.
I recommend to stick with Fibers/Future library when implementing synchronous methods (i've simplified you code, but you should get the idea):

import Future from 'fibers/future';

Meteor.methods({
  'requerimientos.reports.general_4'() {
    const fut = new Future;
    FluentReports.addFile(finalPath, { fileName: fileName, type: 'pdf', fileId: new Mongo.ObjectID()._str, meta: {owner: this.userId, createdAt: new Date()} }, );

    return fut.wait();
  }
});

Or even simpler with Meteor's wrapAsync:

const addFileSync = Meteor.wrapAsync(FluentReports.addFile, addFileSync);
Meteor.methods({
  'requerimientos.reports.general_4'() {
    return addFileSync(finalPath, { fileName: fileName, type: 'pdf', fileId: new Mongo.ObjectID()._str, meta: {owner: this.userId, createdAt: new Date()} });
  }
});

Hi @dr-dimitru,
many thanks for your recomendation. I ended up using _Meteor.wrapAsync_ and _addFile_ worked fine.
Now, another issue arose when I added some code to return a _download link_ to the client. So, this is my method, with added code to create and return the link:

var addFileSync = Meteor.wrapAsync(FluentReports.addFile, FluentReports);
try { 
    result = addFileSync(finalPath, { fileName: fileName,
            type: 'pdf',
            fileId: new Mongo.ObjectID()._str,
            meta: {owner: this.userId, createdAt: new Date()}
            }); 

    report = FluentReports.findOne({ _id: result._id }); 
} catch(error) { 
    return { 
            error: true, 
            message: `Error: ha ocurrido un error: ${error.message}`, 
    }
}

return { 
    error: false, 
    link: `<a href="${report.link()}" target="_blank">Get report ...</a>`, 
} 

However, when the method returns to the client and I click that link, I get the dreaded error:

Failed to load pdf document.

If a go to the file and do a double-click, it opens fine in the pdf reader.

Of course, I must be doing something wrong, but what could it be?

If you consider it better, I can open a different issue for this one.

Many thanks for your all your efforts, and bye ...

@mgrivera I recommend to take a look on this example

@mgrivera this documentation should help as well

Hi @dr-dimitru , everything is working fine right now. Many thanks for all your help.
The final (condensed) code follows:

1) This is how I coded the meteor method:

'requerimientos.reports.general'() {
       ... ... 
        var addFileSync = Meteor.wrapAsync(FluentReports.addFile, FluentReports);

        let result; 

        try { 
            result = addFileSync(finalPath, { fileName: fileName,
                                              type: 'pdf',
                                              fileId: new Mongo.ObjectID()._str,
                                              meta: {owner: this.userId, createdAt: new Date()}
                                            }); 
        } catch(error) { 
            return { 
                    error: true, 
                    message: `Error: some error has ocurrend: ${error.message}`, 
                }
        }
        return { 
                    error: false, 
                    result: result
                } 
    }

2) This is how I call the method from client:

const getReportGeneral2 = () => {
    Meteor.call('requerimientos.reports.general', (error, result) => {

        if (error || result.error) {
            // report your error 
            return;
        }

        Meteor.subscribe('meteor.files.by.id', result.result._id, () => {

            const report = FluentReports.findOne(result.result._id);    

            if (!report) { 
                // report your error ... 
            } else { 
                const link = ` <a href="${report.link()}?download=true" download="${report.name}" target="_blank">${report.name}$</a> `;
               // show link so user can download the file 
            }
        });
    });
}

3) This is the needed subscription:

import { Meteor } from 'meteor/meteor';
import { FluentReports } from '/imports/api/collections/meteor_files/fluentReports'; 

Meteor.publish("meteor.files.by.id", function (fileId) {
    return FluentReports.collection.find({ _id: fileId });
})

Many thanks again. I'm just beginning to know the library; however I can sense its very well done. And very useful.

@mgrivera I'm glad this was quickly solved

Please, support this project by:

Feel free to close it in case if the issue is solved on your end.

Was this page helpful?
0 / 5 - 0 ratings