5.3 Semantic Versioning, Ranges, and Conflicts
Prerequisites: Maven Basics
Estimated time: 15 minutes
You are ready to continue when: you can explain SemVer and avoid applying npm range syntax to other ecosystems
The manifest is ready, but ^1.2.3, ~=1.4.2, and [1.0,2.0) all look like ways to "allow a range." Pause there: version meaning and a package manager's range syntax belong to different layers and cannot be exchanged by appearance.
SemVer Description of Public API Changes
Assuming the publisher adheres to Semantic Versioning 2.0.0:
| Version Segment | When to Increment |
|---|---|
| MAJOR | Incompatible changes in the public API |
| MINOR | Adding backward-compatible features, or marking public APIs as deprecated |
| PATCH | Fixing backward-compatible errors |
0.y.z is used for initial development, and the public API should not be considered stable. Pre-release versions are lower than their corresponding stable versions; +build metadata does not participate in priority comparisons. The version number expresses the publisher's commitment, and it cannot substitute for change logs and testing.
npm's caret and tilde
{
"dependencies": {
"stable-api": "^1.2.3",
"zero-minor-api": "^0.2.3",
"patch-line": "~1.2.3"
}
}| Syntax | npm Range |
|---|---|
^1.2.3 | >=1.2.3 <2.0.0 |
^0.2.3 | >=0.2.3 <0.3.0 |
^0.0.3 | >=0.0.3 <0.0.4 |
~1.2.3 | >=1.2.3 <1.3.0 |
1.2.3 | Exact match |
The table describes ordinary releases. Prereleases have additional matching rules, so satisfying the numeric bounds does not automatically include them. The package names above are configuration examples, not installation targets; see node-semver prerelease rules.
Caret ranges are narrower in 0.x: ^0.2.3 allows versions below 0.3.0, while ^0.0.3 allows versions below 0.0.4. Check the leftmost non-zero component when determining the upper bound.
Python uses PEP 440 specifiers, such as >=1.2,<2 and ~=1.4.2; Maven ranges are written as [1.0,2.0). The three syntaxes cannot be interchanged.
Conflicts Are Not Always Solved by Installing Two Copies
- Maven typically uses the nearest definition; when multiple artifacts are at the same depth, the one declared first takes precedence.
dependencyManagementcan manage versions, but it does not automatically introduce dependencies. - npm can retain multiple versions of a dependency at different points in the dependency tree, but peer dependencies can still cause conflicts.
- pip typically installs only one version of a given distribution in a virtual environment. When constraints cannot be resolved, the installation should fail.
- Gradle's choice is influenced by configuration, constraints, platform, rules, and lock settings.
Inspect the resolver's decision:
npm explain PACKAGE_NAME
npm ls --all
./mvnw dependency:tree
./gradlew dependencyInsight --dependency NAME --configuration runtimeClasspath
python -m pip checkBefore excluding transitive dependencies, confirm the final runtime classpath and compatibility requirements. Exclusion can inadvertently remove essential classes.
Before You Leave This Page
For ^0.2.3, identify the upper bound <0.3.0. When Maven paths request different versions, inspect depth, declaration order, and dependencyManagement. Then test the proposed upgrade: a lockfile records resolution, but cannot check application behavior.