Weird TextEditor repaint() issue

I am writing a component with an editable number box in the form of a TextEditor. My way to deal with invalid input is to set the text to a darker color (pendingColor) when the user has started editing the number; upon pressing enter, the text will get back to its original color (validColor) if and only if the input was a valid number.

In addition to this, (upon pressing enter, if the input is valid) the input will get normalized, so e.g. " - 36,5 " gets turned into “-36.5”.

Here is my definition of the two editor callbacks:

editor.onTextChange = [&]() {
    editor.applyColourToAllText(pendingColor);
    editor.repaint();
};

editor.onReturnKey = [&]() {
    std::optional<float> v = parseNumber(editor.getText());
    if(v.has_value()) { // success! input was valid
        // TODO update listener!!!
        editor.setText(juce::String(v.value())); // turning the parsed value back into a String normalizes it
        // my issue: the following line does not always apply
        editor.applyColourToAllText(validColor);
    } else {
        editor.applyColourToAllText(pendingColor); // should already be that color, but we apply it again just in case
    }
    editor.repaint();
};

Now my issue is, if the number needed to be normalized (e.g. juce::String(v.value()) is different from the original editor.getText()), the color doesn’t update. The text still gets updated to its normalized version.

What puzzles me, and makes me think this is not a trivial mistake, is that if the normalized version of the number is the same as the original number input, the color updates just fine. But conceptually, the same happened in both cases! : valid user input got normalized; the only difference is that in one case, the normalized version is the same as the original one. And yet the program behaves differently.