-
Notifications
You must be signed in to change notification settings - Fork 0
Can't Happen
A can't happen says that an event cannot legitimately arrive in this state at all. There is no prescribed model level recovery, so if a running system does deliver one, the model execution platform is left to clean up the mess.
There are two ways a state ends up with a can't happen response, and the difference matters.
List the event under the state's can't happen section and say why:
state OPENING
activity
transitions
Door opened > OPEN
Passenger close > CLOSING
can't happen
Door closed
Door is opening, so it should not detect ‘closed’.
Door blocked
Block can only be reported while closing the door. (door jams while opening are
not modeled, in this release anyway)
Unlock
<Cabin not moving> Cabin is not able to progress to a state where it can send this event while we are
opening the door.
The grammar:
cant_happens = cant_happen_header response*
cant_happen_header = "can't happen" EOL*
response = INDENT event_name (SP tag)? EOL* explanation?
An unindented can't happen keyword opens the section — the contracted spelling, always — each event name
follows on its own indented line, and its explanation is indented one level further — or, where the
explanation is only a reference to a reason defined elsewhere, on the event line itself. Like ignore, the
section has no -- of its own; the -- closing the state block closes it. See State block grammar and
Reason tags.
Any declared event a state says nothing about is a can't happen. Omission is the default response, so a state block never has to enumerate every event it cannot receive.
That default is not an oversight, but it does mean the file cannot by itself distinguish "I thought about this and it genuinely cannot happen" from "nobody has looked at this yet". What resolves the ambiguity is how the event was declared in the Events block:
- A completion event with no declared response cannot be received here, by definition — it belongs to whichever state issues it. Nothing to decide and nothing to explain, so leaving it out is correct and the overwhelming majority of omissions are this.
- An interaction event with no declared response is an open question. It can arrive at any time, so somebody still has to decide whether it is ignored, transitions somewhere, or genuinely cannot happen — and say why.
So the guidance is simple: let completion events default, and declare every interaction event explicitly. Tooling reading the events block can then list the interaction events still awaiting a decision.
An Ignore means the event legitimately arrives and the right response is to do nothing. A can't happen means the event has no business arriving at all. Both are non-transition responses and both take an explanation, but they describe opposite situations — see Transitions for the three responses side by side.
A cant_happens list on StateBlock_a, holding one Response_a per declared event with event, tag and
explanation fields. Events left to the default do not appear anywhere in the parse result; a consumer
derives them by subtracting every declared response from the events block.
Copyright 2023-2026 © Leon Starr under MIT Open Source License