Hi guys, so Iāve been up for the last 2 days grinding out an NFT collection, but ran into a few roadblocks with the code. This seems to be my last hurdle at the moment and I canāt figure it out. Anyone know How I can fix this? I know it has something to do with having an undefined directory, or being in the wrong directory, but if thatās the case, how I would go about fixing it?
Maybe thereās something wrong with the path of the image file youāre trying to reference? I suppose where you have undefined you should have had a path. I suggest posting some of the code that throws this error since this picture alone is not of much use in regard to troubleshooting.
Thatās whatās confusing to me. So to give more context, Iām using the moralis code directly from their YouTube page on how to make an NFT collection.
Code from Github: https://github.com/ashbeech/moralis-mutants-nft-engine
They explain that any images used for the NFT layers should be placed inside the file āmoralis-mutants-nft-engine-main\inputā and then seperated into different sub folders for their respective layers i.e. āBackgrounds, Base head, Noses, Eyesā etc.
Iām not sure what other code I should be showing. Is there anything specific youād like to see?
I also installed all the dependencies I can think of to get this running. I type ānode index.jsā press enter, and then this is what I get.
it looks like it printed: Mutating 1 of 100000, rarity, dna.
you could look at the code near those messages, and add more console.log there to see what it is trying to access
Thanks, Iāll take another look in that area and see if anything stands out. Iāll update in a bit
So I took a look and thereās only one portion of the code that pings the word āMutatingā. This is that whole section. I donāt see what part of this is causing " code: āENOENTā, path: āundefinedā, syscall: āfopenā"
Hereās another screenshot. ISthere something else I should be looking at? You mentioned adding more āconsole.logā. Sorry, Iām a noob, what exactly do you mean?
By adding more console.log I mean adding lines like console.log("here 1")
so that you can check if it made it there on execution in order to identify where is the problem
Okay, think of me as a 5 year old with an IQ of a rock who doesnāt even know what the word āprogrammingā meansā¦ You said add a line of code like "console.log(āhere 1ā) to check if execution works. When you say that, this is what goes through my head -> "Iām looking at the code, I already see a ton of āconsole.logā everywhere, Iām being told to add "console.log(āhere 1ā), but I neither know where I should be adding this line of code, how it should be added, nor understand what (āhere 1ā) means in terms of what I should replace āHereā and ā1ā with. When I said I was a noob, I meant it. I need literal step by step help, I donāt want to break this code by adding in more lines of code without understanding where or how to add them. Thatās going to break things even more and cause more hell. Iām looking everywhere, for the answer and I canāt find it. If I could Iād go ask Mr.Ash directy (the guy who wrote the code), but letās be honest, thatās not going to happen. The guy way too busy and he has no idea who I am.
Iāve been working on this for countless hours now with no luck. Iām stuck in this one spot.
you can put that line directly how it is now, somewhere between current lines of code, and when executing you should see that string āhere 1ā at console if the execution made it there.
Okay cool. So āhere 1ā does show up. This is what I got. It exits right after however and nothing else happens.
Now, that directory it shows āC:\Program Files\nodejs\node.exe .\index.jsā but that isnāt where the actual project file is with all the images and ācanvasā which could be why it canāt pull any of the img srcās, possibly. Could that be the issue or am I just reading this wrong?
Please paste code from line 300 to 400 or even to the end. Screenshots are not of much use.
āC:\Program Files\nodejs\node.exe .\index.jsā
āC:\Program Files\nodejs\node.exe .\index.jsā is the location for the node interpreter
.\index.js is the location of the file youāre trying to run, so thatās okay.
Your issue might be either not correctly declaring paths or there is some logic error in your code.
Here is code from index.js
line 300 to End
console.log("# - Generating your NFT collection");
console.log("##################");
console.log();
// clear meta data from previous run
writeMetaData("");
// prepare dnaList object
rarityWeights.forEach((rarityWeight) => {
dnaListByRarity[rarityWeight.value] = [];
});
// create NFTs from startEditionFrom to editionSize
let editionCount = startEditionFrom;
while (editionCount <= editionSize) {
console.log("-----------------");
console.log("Mutating %d of %d", editionCount, editionSize);
// upload to ipfs
const saveFile = async () => {
// get rarity from to config to create NFT as
let rarity = getRarity(editionCount);
console.log("- rarity: " + rarity);
// calculate the NFT dna by getting a random part for each layer/feature
// based on the ones available for the given rarity to use during generation
let newDna = createDna(layers, rarity);
while (!isDnaUnique(dnaListByRarity[rarity], newDna)) {
// recalculate dna as this has been used before.
console.log(
"found duplicate DNA " + newDna.join("-") + ", recalculate..."
);
newDna = createDna(layers, rarity);
}
console.log("- dna: " + newDna.join("-"));
// propagate information about required layer contained within config into a mapping object
// = prepare for drawing
let results = constructLayerToDna(newDna, layers, rarity);
let loadedElements = [];
// load all images to be used by canvas
results.forEach((layer) => {
loadedElements.push(loadLayerImg(layer));
});
let attributesList = [];
await Promise.all(loadedElements).then((elementArray) => {
// create empty image
ctx.clearRect(0, 0, width, height);
// draw a random background color
drawBackground();
// store information about each layer to add it as meta information
attributesList = [];
// draw each layer
elementArray.forEach((element) => {
drawElement(element);
attributesList.push(getAttributeForElement(element));
});
// add an image signature as the edition count to the top left of the image
signImage(`#${editionCount}`);
// write the image to the output directory
});
dnaListByRarity[rarity].push(newDna);
const base64ImgData = canvas.toBuffer();
const base64 = base64ImgData.toString("base64");
let filename = editionCount.toString() + ".png";
let filetype = "image/png";
// save locally as file
fs.writeFileSync(`./output/${filename}`, canvas.toBuffer(filetype));
console.log(
"Mutant " + editionCount.toString() + " a resident of Moralis"
);
imageDataArray[editionCount] = {
editionCount: editionCount,
newDna: newDna,
attributesList: attributesList,
};
};
const handleFinal = async () => {
// write image files
const imageData = await saveFile();
};
await handleFinal();
// iterate
editionCount++;
}
ipfsArray = [];
promiseArray = [];
for (let i = 1; i < editionCount; i++) {
let id = i.toString();
let paddedHex = (
"0000000000000000000000000000000000000000000000000000000000000000" + id
).slice(-64);
promiseArray.push(
new Promise((res, rej) => {
fs.readFile(`./output/${id}.png`, (err, data) => {
if (err) rej();
ipfsArray.push({
path: `images/${paddedHex}.png`,
content: data.toString("base64"),
});
res();
});
})
);
}
Promise.all(promiseArray).then(() => {
axios
.post(api_url, ipfsArray, {
headers: {
"X-API-Key": xAPIKey,
"content-type": "application/json",
accept: "application/json",
},
})
.then((res) => {
console.log("IMAGE FILE PATHS:", res.data);
image_CID = res.data[0].path.split("/")[4];
console.log("IMAGE CID:", image_CID);
// pass folder CID to meta data
uploadMetadata(image_CID);
})
.catch((err) => {
console.log(err);
});
});
writeMetaData(JSON.stringify(metadataList));
console.log("#########################################");
console.log(āWelcome to Rekt City - Meet the Survivorsā);
console.log("#########################################");
console.log();
};
// Initiate code
startCreating();
console.log(āhere 1ā)
Next time when posting code on the forums please post code formatted using the integrated code highlighting.
Most likely your error is ocurring during either of these lines:
fs.writeFileSync(`./output/${filename}`, canvas.toBuffer(filetype));
fs.readFile(`./output/${id}.png`, (err, data) => {
if (err) rej();
ipfsArray.push({
path: `images/${paddedHex}.png`,
content: data.toString("base64"),
});
Since the error gives some hint about āfopenā I suppose itās rather the read one than the write one.
This line here:
fs.readFile(`./output/${id}.png`, (err, data) => {
Using methods such as Crypto Kid provided, try either logging the path to the console.
console.log(`./output/${id}.png`);
If the path returned is the correct one, try using an absolute path and check if the error persists.
Thanks, Iāll make sure to post code correctly next time. I rarely ever use forums so I need to get used to this.
As for the code you pointed out, that very well could be the case, but it wouldnāt make sense considering those are ā./output/ā commands telling the file where to save the NFTs after theyāre created. The ā./inputā folder is where all my layers go that canvas is supposed to pull from to use to whip up an NFT and then send it to the ā./output/ā folder. The Problem is I canāt eve get to that step if the program canāt even create the NFTs in the first place let alone āoutputā them. Even the comment right above the lines of code you pasted says ā// save locally as a fileā denoting that these are save functions. I could be completely brain dead about this though.
I did paste in that code āconsole.log(./output/${id}.png
);ā to see what it returns however and I got this
Mutating 1 of 10000
- rarity: rare
- dna: 01--03-04-01-02-07-03-04-03
C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:450
console.log(`./output/${id}.png`);
^
ReferenceError: id is not defined
at Object.<anonymous> (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:450:25)
at Module._compile (node:internal/modules/cjs/loader:1097:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47
Node.js v17.1.0
PS C:\Users\Eli\Documents\moralis-mutants-nft-engine-main>
Also what do you mean by try using absolute path, how would I do that and where would I input it? Remember, think of me as having the IQ of a rock. I need detailed instructions. What you might take for grated as being a given is important to someone like me whoās primarily an artist, 3d modeler, not a programmer.
I did take a stab at it however, modified the line of code to this -
fs.readFile(`C:/Users/Eli/Documents/moralis-mutants-nft-engine-main/output/${id}.png`, (err, data) => {
However nothing changed, still having the same ENOENT, no such file or directory āundefinedā error.
The error still pops up because the id variable is undefined, thus resulting the error. You use ` for being able to use stuff like ${id}
but that kinda breaks up the code highlighting utility. The code is hard to read. Upload the relevant code to pastebin.com and link the paste here.
Iām not the one who coded ${id} into this. This is code straight from the Moralis team, almost near bone stock straight from github. This the original Moralis video where I found the code from.
He doesnāt mention anything about changing ${id} in any of the videos. Thatās why Iām here because he glosses over a few things in the video and doesnāt mention any remedies for possible errors, especially this āundefinedā error. If you watch this video youāll have a complete idea of what Iāve done to the code (nearly nothing) and yet mine doesnāt work, but his does. again, the whole code is straight from Ash Beechās Moralis github.
Hereās the full stock code for the Index.js file from Github, you can scroll through it there. The only lines Iāve changed are the few lines he says to change in the video. (the video is short, itās like 15min).
https://github.com/ashbeech/moralis-mutants-nft-engine/blob/main/index.js
What keeps sticking out to me is this one line that points to some kind of issue with a canvas file called image.js, specifically line 91.
When I execute ānode index.jsā and I get this
PS C:\Users\Eli\Documents\moralis-mutants-nft-engine-main> node index.js
##################
# Generative Art #
# - Generating your NFT collection
##################
-----------------
Mutating 1 of 10000
- rarity: rare
- dna: 01--03-03-02-02-07-03-04-04
C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\node_modules\canvas\lib\image.js:91
SetSource.call(img, src);
^
Error: ENOENT, No such file or directory 'undefined'
at setSource (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\node_modules\canvas\lib\image.js:91:13)
at Image.set (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\node_modules\canvas\lib\image.js:62:9)
at C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\node_modules\canvas\index.js:34:15
at new Promise (<anonymous>)
at C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:83:25
at new Promise (<anonymous>)
at loadLayerImg (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:82:10)
at C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:344:29
at Array.forEach (<anonymous>)
at saveFile (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:343:15)
at handleFinal (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:389:31)
at startCreating (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:392:11)
at Object.<anonymous> (C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\index.js:448:1)
at Module._compile (node:internal/modules/cjs/loader:1097:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10) {
errno: 2,
code: 'ENOENT',
path: 'undefined',
syscall: 'fopen'
}
See at the top, right after the ā-dnaā¦ā line where it points to this line of code that says
C:\Users\Eli\Documents\moralis-mutants-nft-engine-main\node_modules\canvas\lib\image.js:91
SetSource.call(img, src);
^
Itās pointing to the ācallā function in line 91.
I tried debugging the whole program all night and sure enough thatās where it breaks. I looked into the image.js file that itās referencing, but I donāt know how to fix it.
This is the code for the image.js file in Canvas. The line āSetSource.call(img, src);ā is all the way at the bottom. 3rd to last line of code.
'use strict';
/*!
* Canvas - Image
* Copyright (c) 2010 LearnBoost <[email protected]>
* MIT Licensed
*/
/**
* Module dependencies.
*/
const bindings = require('./bindings')
const Image = module.exports = bindings.Image
const util = require('util')
// Lazily loaded simple-get
let get;
const {GetSource, SetSource} = bindings;
Object.defineProperty(Image.prototype, 'src', {
/**
* src setter. Valid values:
* * `data:` URI
* * Local file path
* * HTTP or HTTPS URL
* * Buffer containing image data (i.e. not a `data:` URI stored in a Buffer)
*
* @param {String|Buffer} val filename, buffer, data URI, URL
* @api public
*/
set(val) {
if (typeof val === 'string') {
if (/^\s*data:/.test(val)) { // data: URI
const commaI = val.indexOf(',')
// 'base64' must come before the comma
const isBase64 = val.lastIndexOf('base64', commaI) !== -1
const content = val.slice(commaI + 1)
setSource(this, Buffer.from(content, isBase64 ? 'base64' : 'utf8'), val);
} else if (/^\s*https?:\/\//.test(val)) { // remote URL
const onerror = err => {
if (typeof this.onerror === 'function') {
this.onerror(err)
} else {
throw err
}
}
if (!get) get = require('simple-get');
get.concat(val, (err, res, data) => {
if (err) return onerror(err)
if (res.statusCode < 200 || res.statusCode >= 300) {
return onerror(new Error(`Server responded with ${res.statusCode}`))
}
setSource(this, data)
})
} else { // local file path assumed
setSource(this, val);
}
} else if (Buffer.isBuffer(val)) {
setSource(this, val);
}
},
get() {
// TODO https://github.com/Automattic/node-canvas/issues/118
return getSource(this);
},
configurable: true
});
// TODO || is for Node.js pre-v6.6.0
Image.prototype[util.inspect.custom || 'inspect'] = function(){
return '[Image'
+ (this.complete ? ':' + this.width + 'x' + this.height : '')
+ (this.src ? ' ' + this.src : '')
+ (this.complete ? ' complete' : '')
+ ']';
};
function getSource(img){
return img._originalSource || GetSource.call(img);
}
function setSource(img, src, origSrc){
SetSource.call(img, src);
img._originalSource = origSrc;
}