51

I am currently using Babel.

I did the following before with require:

try {  
    var myModule = require('my-module');
} catch (err) {
    // send error to log file
}

However when trying to do this with import:

try {  
    import myModule from 'my-module';
} catch (err) {
    // send error to log file
}

I get the error:

'import' and 'export' may only appear at the top level

Now I understand that import is different to require. From reading Are ES6 module imports hoisted? import hoists which means the imports are loaded before code execution.

What I did before was that if any requires failed a log was created which alerted me via email (sending logs to logstash etc.). So my question boils down to the following.

How does one handle import errors in a good practice fashion in nodejs? Does such a thing exist?

6
  • Did you use Babel ? Commented Aug 14, 2016 at 20:09
  • @Tugrul Ah yes I do, I should of mentioned this. Commented Aug 14, 2016 at 20:10
  • 1
    I have no question now:) Commented Aug 14, 2016 at 20:11
  • 1
    I think that if you need conditional loading of modules (or need to catch errors when loading them), you have to stick to using require(). See also this question and its answers. Commented Aug 14, 2016 at 20:11
  • Try to look into System.import, it's not implemented in babel though Commented Aug 14, 2016 at 20:36

4 Answers 4

32

You can't catch static imports errors (cf. Boris' answer)

Yet, you could use a dynamic import() for that.

It's now supported by all evergreen browsers & Node, and is part of the standards since ES2020.

class ImportError extends Error {}

const loadModule = async (modulePath) => {
  try {
    return await import(modulePath)
  } catch (e) {
    throw new ImportError(`Unable to import module ${modulePath}`)
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

The dynamic import() returns a Promise and thus you can also use the Promise-style of handling errors: import(modulePath).catch(e => Promise.reject("Module " + modulePath + " not found.")).then(module => { /* use module here */ console.log(module); }). See also stackoverflow.com/a/47755315/341201
9

[2021 Edit] Look at Caveman answer for a more up to date answer allowing to make dynamic import

This talk give it away : https://github.com/ModuleLoader/es-module-loader/issues/280 and agree with what you said.

import only works at the base level. They are static and always load before the module is run.

So you can't do a code check.

But, the good news is that as it's static, it can be analysed, tools like webpack throw errors at build time.

1 Comment

Note that this answer is no longer entirely correct: you can't do this for static imports but you can do this for dynamic imports which return a promise that you can either .catch() in a promise chain, or try await/catch if you're in an async function.
8

Supplementary dynamic import.

class ImportError extends Error {}

const loadModule = async (modulePath) => {
  try {
    return await import(modulePath)
  } catch (e) {
    throw new ImportError(`Unable to import module ${modulePath}`)
  }
}

async function main() {
  // import myDefault, {foo, bar} from '/modules/my-module.js'
  const { default: myDefault, foo, bar } = await loadModule('/modules/my-module.js')
}

or chained_promises

import("/modules/my-module.js").then(module=>{
  module.foo()
  module.bar()
}).catch(err=>
  console.log(err.message)
)

or Destructuring assignment

import("/modules/my-module.js").then(({foo, bar})=>{
  foo()
  bar()
}).catch(err=>
  console.log(err.message)
)

Comments

-9

A very modern answer to this now since cloud services is becoming the norm is to let the import fail and log to stderr as cloud services logs from stderr to their logging service. So basically you don't need to do anything.

1 Comment

well, to give a better perspective on the problem here, in my case the failing import crashed the entire app since the "problematic" library is added in the main.js file. Now I can either complain that the library I'm using doesn't handle a specific case (incognito iframe to be precise) and to tell my users to blame them or - which I choose - to catch the error and to provide a fallback so that my users can keep using the app. And for the latter I need a way to catch errors during import which is what the original question is about.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.