What does semantic versioning imply about parameter name changes?

Short answer: yes, I think that would constitute an API break and thus potentially increment the major version number. Note the caveats below, though.


When you expose a public/external API, you take on an extra "duty of care" to think carefully about changes to the interface. This includes, for example, putting off a potential improvement to avoid breaking backwards compatibility*. Any change that would affect any code legitimately** using your interface should be considered very carefully when you're maintaining an API.

The specification for semantic versioning is unambiguous:

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API.

Changing the names of parameters, as you have identified in the question, introduces a backwards incompatibility for code passing arguments by keyword.

However, rather than say that this change should increment the major version, I would conclude instead that the change should not be made, or at least not in isolation - it's too minor a change to justify the major increment that potentially breaking existing valid code would entail. Except for the case that either:

  1. It's part of some larger bundle of important changes; or
  2. There is a really good reason for the change that isn't shown in your example (some show-stopping bug, or other feature that relies on it);

I would put off the change altogether. It's better to move more slowly and ensure that you continue to meet your semantic versioning contract, making such changes only with compelling grounds to do so.


From Python 3.8 you can specify positional-only parameters, with exactly this kind of issue being called out in the PEP as part of the justification (emphasis mine):

If a caller of an API starts using a keyword argument, the library author cannot rename the parameter because it would be a breaking change.

In this case, if the original definition had been:

def foo(x, y, /):

then renaming the parameters would not be a breaking change.


* As we're in the Python tag, consider integer division, that, despite being acknowledged as a mistake by the BDFL, remains in 2.x releases to this day.

** I say "legitimately" to exclude code not using it as officially documented, for example by accessing private-by-convention attributes - they should expect to get inconvenienced on occasion! Therefore if you'd predicted this change and it was clearly specified that only positional arguments should be used, this change would be OK, but that would be an odd choice.