We encountered this while developing a Bazel integration that builds component documentation separately. Each component exports its own needs.json. We then load multiple component inventories through needs_external_needs to check their needs together.
These inventories belong to the same published documentation project, so they share the same base_url, even though each comes from a different documentation build and has a different json_path.
If two components independently define the same need ID, each component builds successfully on its own. When loading their inventories together, we expect a duplicate-ID warning. Instead, the second import silently replaces the need from the first inventory.
We observed this with Sphinx-Needs 8.5.0. In load_external_needs, an existing external need is deleted before importing the new one if:
source["base_url"] in need["external_url"]
Because our inventories share a base_url, this condition treats the second inventory as a reload of the first source. Using different base URLs makes the duplicate-ID warning appear.
This has several consequences:
- Accidental duplicate IDs in separate inventories go undetected, so a successful build can hide conflicting definitions.
- If the inventories contain different versions or variants of a need with the same ID, the earlier definition is silently replaced. The replacement check does not compare the definitions or distinguish their source inventories or imported versions.
- The resulting need depends on import order: the last definition loaded wins. References to that ID then resolve to the surviving definition, which may be a different version or variant than intended.
Expected behavior
Reloading the same external source should be able to replace the needs it previously imported. Loading a different source should not be treated as a reload solely because it shares a base_url with an existing need. If both sources define the same need ID, the normal duplicate-ID validation should report it.
This deletion logic was introduced by PR #389, which fixed issue #341: Build with needs_external_needs is unstable. The original change adding del_need(app, ext_need_id) can be seen in the PR diff.
We encountered this while developing a Bazel integration that builds component documentation separately. Each component exports its own
needs.json. We then load multiple component inventories throughneeds_external_needsto check their needs together.These inventories belong to the same published documentation project, so they share the same
base_url, even though each comes from a different documentation build and has a differentjson_path.If two components independently define the same need ID, each component builds successfully on its own. When loading their inventories together, we expect a duplicate-ID warning. Instead, the second import silently replaces the need from the first inventory.
We observed this with Sphinx-Needs 8.5.0. In
load_external_needs, an existing external need is deleted before importing the new one if:Because our inventories share a
base_url, this condition treats the second inventory as a reload of the first source. Using different base URLs makes the duplicate-ID warning appear.This has several consequences:
Expected behavior
Reloading the same external source should be able to replace the needs it previously imported. Loading a different source should not be treated as a reload solely because it shares a
base_urlwith an existing need. If both sources define the same need ID, the normal duplicate-ID validation should report it.This deletion logic was introduced by PR #389, which fixed issue #341: Build with needs_external_needs is unstable. The original change adding
del_need(app, ext_need_id)can be seen in the PR diff.