Quick answer: Branching ending bugs come from flag and condition state: the story flags set during play, the values those flags hold, the conditions the ending selector evaluated, and which branch it chose and why. Players who earn one ending and receive another are hitting a flag that was never set, a stale value, or a condition with the wrong logic. Capture the flags, the evaluated conditions, and the chosen branch and the wrong ending explains itself.
A branching ending is the payoff for an entire playthrough, the moment the game tells the player their choices mattered. When it gives the wrong ending, it does not just bug out, it betrays the promise the whole game made. A player who spared everyone gets the bloodthirsty ending, a romance carefully built pays off with the wrong character, a secret ending refuses to trigger despite every requirement met. Underneath, an ending selector evaluates a set of story flags against conditions and picks a branch. The bugs hide in which flags were set, what values they hold, and how the selector reads them. This post is about capturing ending state so a wrong ending report names the flag or condition at fault.
Endings are a decision over accumulated flags
A branching ending is the output of a decision function that reads story state, the flags and counters and choices accumulated across the whole game, and selects one branch. That state is set in a hundred scattered places during play, which is exactly why endings break. A flag that a key choice was supposed to set, but a dialogue path missed, leaves the selector reading a default that points at the wrong branch. The player experiences a betrayal of their choices, but the cause is a single unset or mis set flag buried somewhere far earlier in the playthrough.
The brutal part is that the bug is invisible until the very end, and by then the playthrough is over. A player cannot replay twenty hours to diagnose it, and you cannot reproduce it without their accumulated flag state. This is the strongest case for capturing the full set of ending relevant flags at the moment the ending is selected. The wrong ending is never random; it is the deterministic output of a specific flag configuration, and once you can see that configuration the fault is no longer a mystery but a value you can read.
The ending state to capture
Capture the complete set of story flags the ending selector reads, each with its current value, the full set of conditions the selector evaluated, the result of each condition, and the branch it ultimately chose with the reason. With those fields a wrong ending report becomes an audit of the decision. You read the flags, check each against what the player says they did, and find the one flag whose value contradicts the player's actions. A spared everyone player whose killed someone flag reads true points straight at a flag set by mistake somewhere in the game.
Capture the evaluation order too, because ending selectors are often a cascade of conditions where the first match wins. If a broad condition is checked before a more specific one, the specific ending can never trigger, and the player who met every secret requirement gets a generic ending instead. Recording which conditions passed and which branch matched first reveals this ordering bug directly. The captured trace shows the secret condition passing but a broader condition earlier in the cascade claiming the branch, which is an ordering fix rather than a flag fix.
Missing and stale flags
The most common ending bug is a flag that was never set. A pivotal choice is supposed to record itself, but one of the dialogue branches that reaches the same outcome forgot to set the flag, so players who took that specific path arrive at the ending with the wrong state. Capturing every ending relevant flag with its value exposes this when a flag the player clearly earned reads as its default. From there you trace back to which choice should have set it and find the path that missed the assignment, a far faster route than replaying to guess.
Stale flags are the subtler cousin. A flag set early and meant to be updated by later events can keep an outdated value if an update path is missed, so the ending reflects an old state the player has since changed. A player who betrayed an ally and then redeemed themselves might still get the betrayal ending because the redemption never cleared the betrayal flag. Capturing the flag values at ending time, ideally with the last event that wrote each one, separates a never set flag from a never updated one, which are different bugs in different parts of the story scripting.
Condition logic and counter thresholds
Many endings depend not on single flags but on counters and thresholds: rescued more than half the survivors, accumulated enough renown, made mostly merciful choices. These introduce comparison logic that breaks in familiar ways, an off by one at the boundary, a count that missed some increments, or a comparison using the wrong operator. Capturing the counter values and the threshold each condition compared against lets you check the arithmetic. A player who rescued exactly the boundary number and got the wrong ending is hitting a strict versus inclusive comparison bug visible the moment you see the count and the threshold side by side.
Combined conditions multiply the failure modes. An ending that requires several flags true and a counter above a threshold can fail if any single term is wrong, and from outside the player cannot tell which term failed. Capturing the result of each individual condition, not just the final branch, isolates the failing term immediately. You see three of four conditions passed and the fourth failed, and you know exactly where to look, instead of re deriving the entire ending logic from a one line report that the wrong ending played. The per condition results turn a compound bug into a single pinpointed term.
Setting it up with Bugnet
Bugnet's in-game report button captures game state automatically, so an ending report arrives with the full flag set and the selector trace attached rather than a player insisting they made the right choices. Serialize the ending state into custom fields: every ending relevant flag with its value and last writer, the counters with their thresholds, the per condition evaluation results, and the chosen branch with its reason. When a report says I got the wrong ending, you open it and the flag set contradicts the player's described choices, or the condition trace shows the intended branch losing to an earlier match.
Occurrence grouping folds matching ending reports into one issue with a count, so a missed flag on a common dialogue path that misroutes many players surfaces as a single high priority entry instead of scattered narrative complaints. You can filter by the chosen branch custom field to find every report that received a given ending, and compare their flag sets to spot the one flag that is wrong across all of them. With the flags, conditions, and chosen branch in one dashboard, a bug that took an entire playthrough to manifest becomes a quick audit of the decision the player could never inspect.
Testing the ending matrix
The durable defense is testing the ending selector against constructed flag states, since you cannot rely on full playthroughs to cover every branch. Build a matrix of representative flag and counter configurations, one per intended ending plus the tricky boundaries, and assert the selector chooses the right branch for each. Because your reports serialize the exact flag set, any wrong ending replays into a test directly: feed the captured flags into the selector and assert it now chooses the ending the player earned, which both reproduces the bug and verifies the fix.
Test the condition ordering specifically so that specific endings always win over broader ones, and test counter boundaries with inclusive and exclusive values so off by one bugs cannot regress. The teams that ship branching endings players trust are the ones who can see the full flag state and the selector's reasoning at the moment of the ending, rather than hoping the scattered flag writes across the game all fired correctly. When the decision is observable and the matrix is tested, the wrong ending stops being a heartbreaking mystery and becomes a single flag or condition you can fix with confidence.
A wrong ending is never random; it is a deterministic output of one bad flag. Capture the flags and the selector trace and the betrayal becomes a fix.