Hawk has pointed out the problem. It seems that the particular object you are interacting with changes after interacting with it - this is not the case for all objects, but appears to be the case here.
Regarding the structure of your code, you should always aim to make the script deterministic based on game state. This essentially means that you should be executing a single game interaction per onLoop iteration. This way, should any given interaction fail (which can happen for many reasons as we are automating a live game here), the script will always be in a state to retry. Here's what I mean in your context with pseudocode:
onLoop {
RS2Object trapdoor = getObjects().closest("Trapdoor");
if (trapdoor has action "open") {
if (trapdoor.interact("open")) {
conditional sleep until trapdoor is open;
}
} else if (trapdoor has action "climb-down") {
if (trapdoor.interact("climb-down")) {
conditional sleep until climb down is successful (e.g. correct z index)
}
}
}
Note that for every iteration of onLoop here, only one interaction can ever happen. Also note that this example doesn't take into account the particular issue you are experiencing wrt. the trapdoor object changing. You'll probably need to initialise two objects (e.g. trapdoorOpen and trapdoorClosed) and act based on which one is null.
Hope that helps
Apa