Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Revised code, same problem. Why am I getting a NOENT using the node core module 'fs'?

This a repeat question (unanswered) but I have revised and tightened up the code.

This is a Node API. I need to read and write JSON data. I am using the Node core module 'fs', not the npm package by the same name. I have extracted the particular area of concern onto a standalone module that is shown here:

'use strict';

/*==================================================
    This service GETs the list of ids to the json data files 
    to be processed, from a json file with the id 'ids.json'.
    It returns and exports idsList (an array holding the ids of the json data files)
    It also calls putIdsCleared to clear the 'ids.json' file for the next batch of processing
==================================================*/

//  node modules
const fs          = require('fs');
const config      = require('config');

const scheme      = config.get('json.scheme')
const jsonPath    = config.get('json.path');
const url         = `${scheme}${jsonPath}/`;
const idsID       = 'ids.json';
const uri         = `${url}${idsID}`;
let idsList = [];

const getList = async (uri) => {
    await fs.readFile(uri, 'utf8', (err, data) => {
        if (err) {
            return(console.log( new Error(err.message) ));
        }
        return jsonData = JSON.parse(data);
    })
}

//  The idea is to get the empty array written back to 'ids.json' before returning to 'process.js'
const clearList = async (uri) => {
    let data = JSON.stringify({'ids': []});
    await fs.writeFile(uri, data, (err) => {
        if (err) {
            return (console.log( new Error(err.message) ));
        }
        return;
    })
}

getList(uri);

clearList(uri)

console.log('end of idsList',idsList);

module.exports = idsList;

Here is the console output from the execution of the module:

Error: ENOENT: no such file or directory, open 'File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json'
    at ReadFileContext.fs.readFile [as callback] (/Users/doug5solas/sandbox/libertyMutual/server/.playground/ids.js:24:33)
    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:235:13)
Error: ENOENT: no such file or directory, open 'File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json'
    at fs.writeFile (/Users/doug5solas/sandbox/libertyMutual/server/.playground/ids.js:36:34)
    at fs.js:1167:7
    at FSReqWrap.oncomplete (fs.js:141:20)

I am being told there is no such file or directory. However I can copy the uri (as shown in the error message)

File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

into the search bar of my browser and this is what is returned to me:

{
    "ids": [
        "5sM5YLnnNMN_1540338527220.json",
        "5sM5YLnnNMN_1540389571029.json",
        "6tN6ZMooONO_1540389269289.json"
    ]
}

This result is the expected result. What the heck is going on?

3 Answers

Seth Kroger
Seth Kroger
56,413 Points

I had to look this one up in the NodeJS docs because this subtlety isn't obvious: https://nodejs.org/api/fs.html#fs_url_object_support

If you're using a file:// URI for the path you need to create a URL object from it and pass that. Otherwise a string would just be considered a vanilla filesystem path.

Seth:

Thanks!!!!!

I'm not sure how long it would have taken me on my own to find that. I find the documentation for products like Node and Express hard to follow and designed, it appears, for people who know what they are doing. I have refactored the code to use the new URL() constructor and it works brilliantly. Now, my next challenge is to raise the idsList variable up through the scopes to make it available at the module level. It is the value I am trying to export from the module.

But, at least I have it now.

One question still haunts me, though. I 'get' that using 'file://' required the constructor. What eludes me is this: if I try to switch and use:

localhost:3000//Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

as the path. And, I do not use the constructor, but I use it as a flat string, I get a NOENT style error. I am not sure why that is. The reason that is important for me is this.

file:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

is fine in a localhost (development) environment. But, it will not fly when I have to move the API to test and then to production.

Hi Doug how are you running this? Are you within TreeHouse workspace or a local server?

If you open this:

File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

In your browser and it's giving you the correct json file then it is the callback function which is the problem

Liam I am running this on my localhost. I used:

File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

because when I tried it with:

localhost:3000//Users/doug5solas/sandbox/libertyMutual/server/api/ids.json

not only did it NOT work programmatically, it didn't work manually. The 'File:///...' was a desperation move. My mind tells me that "localhost:3000..." is the proper way to do it.

In what way is the callback the problem? My understanding is, this is the callback:

(err, data) => {
        if (err) {
            return(console.log( new Error(err.message) ));
        }
        return jsonData = JSON.parse(data);
    })