You can avoid illegal states by starting in a legal state and disallowing transitions into illegal states.
The problem is enforcing that in a system complex enough to get useful work done.
The code you posted is trivial enough that it can be fixed simply by adding another type to represent your missing state.

You seem to be using some Java like language so here's one way to fix your code:
public class Stopped {
Started start() { ... }
}
public class Started {
Stopped stop() { ... }
}
Here the compiler is enforcing that these methods be called in order. I don't even have to look at the using code.
But add a simple feature and watch it all fall apart. Lets say we're simulating an internal combustion engine. The kind in your car. That's seems like it should be fine. Those start and stop all the time.
Lets add a throttle. You know, a gas peddle. When started it makes the engine rev. When stopped it floods the carburetor.
That actually works fine. Add a little polymorphism. Started and stopped now both implement a throttle interface. Spiffy.
Then someone up and decides that throttles are not binary. They go from 0% to 100% open. So they decide to pass numbers from 0 to 100 to the throttle method. Sounds fine. But they used an int.
Can you see the problem yet? Sure 0 works. 100 works. Anything in between works. So we're fine right?
Well no we're not. Before, we didn't have to look at the complex using code. We could prove our code stays in valid states just by reviewing two classes. Now we have to review everything that touches our code.
The problem, of course, is that an int allows more than 0-100. We can pass negative numbers, maybe hoping to go in reverse, and we can ask the engine to give 110%. While that looks great on motivational posters it can easily put us into an invalid, undefined, state.
Now you can, and should, try to fix this with validation but this is what drives us to give up on proving that code works and instead lean on testing. Our code is going out into a wild and wooly world full of code that we may never see. When that code touches our code it could pass whatever.
So what you do, to prevent invalid states, is control transitions, validate input, and test the hell out of it.
A single 4 byte int has billions of states. You going to test all that? Of course not. What you do is something called state space partitioning. Which is a fancy way to say test the limits of your boundaries. In this case you'll want throttle tests for -1, 0, 100, and 101. That tests each side of your upper and lower boundaries.
That should give you something called code coverage. Each branch of code gets exercised by tests. Even the ones that are supposed to throw an error in your face.
This still won't that prove that you can never enter an invalid state. But it's the closest we can come in a language like this.
If you need something more formal and provable, look into Scala.
Illegal state would be created if stop() is called before start()
-- No,stop()
just does nothing, because there is nothing to do.interface ProcessBuilder {Process start();} interface Process {void stop();}
but you can still stop a stopped process.