According to the rules of Semantic Versioning (SemVer), each part of a version number vx.x.x is meant to represent a different type of change — These different change types are primarily defined by their backwards-compatibility.
The major version number (the first in the sequence) is meant to be used for incompatible API changes. The minor version number (the middle one) is meant to be used when introducing new backwards-compatible features. The patch version number (the last one) is meant to be used for backwards-compatible bug fixes.
Although SemVer is a very useful guideline and the definitions above may sound pretty clear, in practice, you may find that figuring out the SemVer classification for certain code changes can sometimes be difficult. If you maintain a library or framework upon which many other projects depend, sometimes even the most trivial ‘bug fix’ can break backwards compatibility for a small subset of your users — This is in part because the line between features and bugs can get blurry at times.
Sometimes other developers’ code may depend on undocumented behaviour in your library/module which looks like a feature but which is actually a bug (or simply a poorly chosen default configuration)— Although the saying “It’s not a bug, it’s a feature” is well known in the industry, the inverse problem is also relatively common when it comes to more complex projects (though we typically don’t like to admit those).
I think that SemVer should be followed as closely as possible, but I also think that it’s important to be aware that for certain scenarios, SemVer is as much art as it is science. Sometimes you need to use your understanding of the project and the ecosystem to make informed probabilistic decisions when it comes to versioning.