Files must be loaded inside setup() or after it has been called

My code has many different object classes which all extend the main class. Each one has its own set of PImages (I have found that the only way to make them work is to loadImage them inside the class constructor, you can see more in my previous discussion).
However, one class doesn’t seem to work, because with the other object classes, I create them in setup(), meaning that their loadImage methods are all run in setup. But with this one, I create a new class during the code and not during setup, so it gives an error saying that “files must be loaded inside setup() or after it has been called”. Though it’s not in setup, it is technically after it’s been called, so I don’t know why it doesn’t work.
Here’s a little bit of code (for context, redsquare is the main class and this class is called inventoryitem).

public class inventoryitem extends redsquare {
	PApplet p;
	public String type;
	public int quantity, itemnumber;
	public String description;
	inventoryitem(PApplet parent, String type, int quantity, int itemnumber) {
		p = parent;
		woodsword_inventory = p.loadImage("woodsword_inventory.png");
		axe_inventory = p.loadImage("axe_inventory.png");
		log_inventory = p.loadImage("log_inventory.png");
		weed_inventory = p.loadImage("weed_inventory.png");
		luckyclover_inventory = p.loadImage("luckyclover_inventory.png");
		redberry_inventory = p.loadImage("redberry_inventory.png");
		blueberry_inventory = p.loadImage("blueberry_inventory.png");
		inventoryslot = p.loadImage("inventoryslot.png");

You can ignore all the random variables like quantity and stuff, those aren’t really necessary.
Again, this issue only happens with this particular object class because the other ones are created in setup() (therefore the images are loaded in setup) while this class is created in the middle of the code.
Any thoughts on what I should do?

Images have to be loaded during or after setup because it needs to set the sketchPath so it knows where to find the image files.

This is probably your problem. Just because a statement appears after / below the setup method it doesn’t mean it will be executed after setup().

I suspect you have a statement like

inventoryitem ii = inventoryitem(this,....);

below setup but not inside a method, in which case it will be executed before setup.

for example here is an example sketch showing order of execution

public int x = 800;  // executed first

public void draw(){
      // executed fourth
}

public void setup(){  
      // executed third
}

public float f = 3.142f;  // executed second.

Actually they can be loaded during settings(): :framed_picture:

Well, the way I load it is during draw(), because during the draw method, if certain conditions are met during the game, it creates a new inventoryitem. So if draw() is executed after setup(), that means that it’s certainly being run after setup() is run.
More specifically, the draw() runs the code of another class (item), and if it detects that the player is within the item, it deletes the item and adds new inventoryitem.
So is there any way I can either fix this problem and let me loadImage normally, or make some kind of loophole to make it work? The only thing I can think of is to somehow create the new inventoryitems in setup(), but that doesn’t make sense because different inventoryitems should be created and deleted off the inventory every once in a while, which would make it so they would have to be created on the spot.
Let me know if you have a new idea or if I understood you wrong.

This sounds like you should give us a minimal MCVE sketch that performs that process using your class.

It is very difficult to get advice by describing what you think code is doing, especially when you think it should be working. Often, the code isn’t doing what you think it is – but it is very hard for others to guess what without being able to look at some actual running code.

Well, it’s hard to give a small amount of code, but here’s some:
This is the item class. It works fine because all of them are created during setup.

public class item extends redsquare {
	PApplet p;
	public String type;
	public int quantity, x, y, elocation;
	public int quantityadd = -1;
	item(PApplet parent, String type, int quantity, int elocation, int x, int y) {
		p = parent;
		woodsword = p.loadImage("woodsword.png");
	}
	public void displayitem(int px, int py) {
		if (px >= x-50 && px <= x+64 && py >= y-50 && py <= y+64) {
			give (type, quantity);
			quantity = 0;
		}

This runs the give method, located within the main class (redsquare).

public void give(String type, int quantity) {
		if (inventory.size() == 0) {
			inventory.add(new inventoryitem(this, type, quantity, inventory.size()+1));
		}

It’s more complicated than that, but all you need to know is that it creates a new inventoryitem within ArrayList inventory.

public class inventoryitem extends redsquare {
	PApplet p;
	public String type;
	public int quantity, itemnumber;
	public String description;
	inventoryitem(PApplet parent, String type, int quantity, int itemnumber) {
		p = parent;
		woodsword_inventory = p.loadImage("woodsword_inventory.png");
	}

However: Interestingly enough, running give to create a new inventoryitem works fine when run from the main class. For example, if during the sketch, in draw, something happens which causes give to be run, it works. But on the other hand, when give is run from class item, it breaks.
I don’t know if any of this code will be helpful but that’s what I have and know so far.

Can you put this code together into the simplest running sketch possible that causes the error?

Honestly, I’d recommend making a copy of your errored sketch, then removing as many things as you possibly can without the error going away. Then share that running sketch to show the error. Along the way you might accidentally find the bug.

We can help you debug a working sketch – an MCVE – one you can run. Usually we can’t debug some snippets you picked out for this kind of problem that don’t run, because we can’t see the error happening and we don’t know for sure that the error is in the snippets you gave!

I don’t actually know if this will work for you, because I use Eclipse IDE and install Processing into it (Proclipsing). But here’s the code anyway. I created a new code from scratch which provides a neat little interface to show you how to make it break and what I know about why it breaks. It’s essentially a white screen with some text.
This requires a few things: Package processing, class Main, class Sub, class Sub2, and image img.png (could be anything as long as it’s small enough, anywhere from 3232 to 100100).
Here is class Main:

//This is project processing2, package processing, class Main and class Sub.
//Sorry for the weird package name, I couldn't change it.

package processing;

import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PFont;
import java.util.ArrayList;

public class Main extends PApplet {
	PApplet p;
	PImage image;
	PFont font;
	//A new Sub is added to list each time you press SPACE.
	//Only one Sub2 is ever added to list2, but I decided to keep it as an ArrayList
	//to keep it consistent.
	ArrayList<Sub> list = new ArrayList<Sub>();
	ArrayList<Sub2> list2 = new ArrayList<Sub2>();
	
	public static void main(String[] args) {
		//starts the PApplet from Eclipse
		PApplet.main("processing.Main");
	}
	public void settings() {
		size(1500, 800);
	}
	public void setup() {
		//font stuff
		font = createFont("Calibri", 30);
		textFont(font);
		list2.add(new Sub2(this));
	}
	public void draw() {
		background(256, 256, 256);
		for(int i = 0; i < list.size(); i++)
			list.get(i).show();
		for(int i = 0; i < list2.size(); i++)
			list2.get(i).show();
		fill (0, 0, 0);
		text("Press SPACE to create new class Sub. This will create an image in the left.\n"
			+ "You will notice that there is an image in the top. This is the Sub2 class. \n"
			+ "Press ENTER to essentially instruct class Sub2 to create an image in the right,\n"
			+ "and make itself invisible.\n"
			+ "However, it does not work because the sketch does not like it when classes are created\n"
			+ "from another class.", 280, 300);
		//These keys is detected in keyPressed()
	}
	public void keyPressed() {
		if (key == ' ')
			list.add(new Sub(this, 500, 600));
		if (keyCode == ENTER)
			list2.get(0).visible = false;
		//When you hit ENTER the first entry in list2 (the only one that exists) becomes invisible.
		//It then creates a new Sub in list.
	}
}

Here is class Sub:

//Sub is the first subclass of Main. It extends Main.
package processing;
import processing.core.PApplet;

public class Sub extends Main {
	//I cannot extend PApplet from this class, so I make a PApplet and do PApplet.method();
	PApplet p;
	Sub(PApplet parent, int x, int y) {
		p = parent;
		image = p.loadImage("img.png");
	}
	public void show() {
		//All this does is create an image while it exists
		p.image(image, 300, 600);
	}
}

And here is class Sub2:

//Sub2 also extends Main, and its primary job is to create Sub classes when ENTER is pressed.
package processing;
import processing.core.PApplet;

public class Sub2 extends Main {
	boolean visible;
	PApplet p;
	Sub2(PApplet parent) {
		p = parent;
		//You must get an image to use (it could be anything, just call it img.png, and try to make it about 100*100 or similar.)
		image = p.loadImage("img.png");
		visible = true;
		//Theoretically, if I press ENTER, it turns visible to false. This turns it invisible, then
		//the if statement goes to else and repeatedly adds new Subs to list.
	}
	public void show() {
		if (visible)
			p.image(image, 500, 100);
		else {
			list.add(new Sub(this, 900, 500));
			//This is where the code breaks. Notice that when you hit SPACE, it creates
			//a Sub in the left of the screen, that's normal.
			//It runs the constructor, doing loadImage normally.
			//HOWEVER: When this code is run (add new Sub), it crashes, saying:
			//"The sketch path is not set."
			//"Files must be loaded inside setup() or after it has been called."
			//This is because when you press SPACE, it creates a new Sub within the Main class.
			//But when you press ENTER, it creates a new Sub within the Sub2 class.
			//I don't know why that difference would cause everything to break.
		}
	}
}

So again, I don’t know if this will work for you. I also don’t know if this will help (is this what I’m supposed to show you?). But if it’s helpful, you can look over it or try to run it. The comments in the code will guide you a little.
Thanks for your patience.