programming.protips.wiki
githubtwitter
/file-reading-race-condition
#file-system #error-handling #race-condition

Don't check if a file exists before reading it

Don't check if a file exists before reading it - just read it, and use a try/catch block to handle the case where the file doesn't exist.

Bad:

function getConfig(configPath) {
  if (!fs.existsSync(configPath)) {
    throw new Error(`Could not read config. Expected ${configPath} to exist`);
  }

  return fs.readFileSync(configPath, 'utf8');
}

Good:

function getConfig(configPath) {
  try {
    return fs.readFileSync(configPath, 'utf8');
  } catch (e) {
    throw new AggregateError([`Could not read config file: ${configPath}`, e]);
  }
}

Why?

The second example protects against race conditions causing a bug. It's possible that the file could appear/disappear in between checking the existance of the file and reading it.

This general coding style is known as "Easier to ask for forgiveness than permission" (EAFP).

(Even if you think it's not a problem for your one-off build script, it could still be a problem if folks run multiple commands at once from multiple windows, or someone later decides to throw xargs around your script. Concurrency can lead to stuff being deleted/read at the same time.)

Further reading