Found while fixing #1567.
isCancellationError in src/utils/errorUtils.ts decides whether the user cancelled by comparing the thrown value against a hardcoded list of literals:
const cancellationMessages = [
"no input given.", // GenericSuggester, InputSuggester, GenericCheckboxPrompt
"No input given.", // GenericInputPrompt, MathModal
"cancelled" // OnePagePreflight
];
return cancellationMessages.includes(error);
Note the two case variants of the same sentence - that is the fragility showing. Ten modals reject with a bare string on dismissal (GenericInputPrompt, GenericWideInputPrompt, MathModal, MultiChoiceSettingsModal, GenericSuggester, InputSuggester, MultiSuggester, GenericCheckboxPrompt, OnePageInputModal x2), consumed across ~40 call sites. Rewording any of those strings - or adding an eleventh modal with a slightly different one - silently turns "the user cancelled" into "an error occurred", with no compiler or test signal.
#1567 removed GenericYesNoPrompt from this list by making it resolve a sentinel instead of rejecting. That works there because boolean already has a natural "no" value. The remaining modals return string / T / string[], which have no natural cancelled value, so rejection is a legitimate signal for them - they just should not be signalling it with an English sentence.
Shape of a fix: a PromptCancelledError class thrown by every prompt, with isCancellationError becoming an instanceof check. The string list has to stay until the last modal is converted, so this is best done one modal per PR with the list shrinking each time.
Found while fixing #1567.
isCancellationErrorinsrc/utils/errorUtils.tsdecides whether the user cancelled by comparing the thrown value against a hardcoded list of literals:Note the two case variants of the same sentence - that is the fragility showing. Ten modals reject with a bare string on dismissal (
GenericInputPrompt,GenericWideInputPrompt,MathModal,MultiChoiceSettingsModal,GenericSuggester,InputSuggester,MultiSuggester,GenericCheckboxPrompt,OnePageInputModalx2), consumed across ~40 call sites. Rewording any of those strings - or adding an eleventh modal with a slightly different one - silently turns "the user cancelled" into "an error occurred", with no compiler or test signal.#1567 removed
GenericYesNoPromptfrom this list by making it resolve a sentinel instead of rejecting. That works there becausebooleanalready has a natural "no" value. The remaining modals returnstring/T/string[], which have no natural cancelled value, so rejection is a legitimate signal for them - they just should not be signalling it with an English sentence.Shape of a fix: a
PromptCancelledErrorclass thrown by every prompt, withisCancellationErrorbecoming aninstanceofcheck. The string list has to stay until the last modal is converted, so this is best done one modal per PR with the list shrinking each time.