Skip to content

Fix: Enforce strict layout validation in Network space#3386

Merged
quaquel merged 4 commits intomesa:mainfrom
Nithurshen:fix-network-layout-validation-3385
Mar 2, 2026
Merged

Fix: Enforce strict layout validation in Network space#3386
quaquel merged 4 commits intomesa:mainfrom
Nithurshen:fix-network-layout-validation-3385

Conversation

@Nithurshen
Copy link
Copy Markdown
Contributor

Summary

This PR fixes a bug where initializing a Network space with an incomplete or empty layout dictionary resulted in a cryptic SciPy ValueError. It introduces strict validation to explicitly catch missing node positions before spatial processing begins.

Bug / Issue

Fixes #3385

When a layout dictionary was provided but was missing entries for certain node IDs, node_positions.get(node_id) returned None. This None value was incorrectly wrapped into a NumPy array (np.array(None)), which bypassed the subsequent pos is not None guard. This invalid position was then passed to scipy.spatial.KDTree, causing a crash with the cryptic error.

Implementation

  • Modified the __init__ method in mesa/discrete_space/network.py. Extracted the position lookup (raw_pos = node_positions.get(node_id)) and added an explicit None check before NumPy conversion. If a node is missing from the layout, the initialization now immediately halts and raises a SpaceException with a clear, Mesa-specific error message detailing the exact missing Node ID.
  • Removed the redundant if pos is not None: guard later in the loop since positions are now strictly validated.

Testing

  • Added a new test test_network_missing_layout_node in tests/discrete_space/test_discrete_space.py.
  • Verified that a completely empty layout (layout={}) and a partially missing layout both correctly raise the expected SpaceException.

Additional Notes

As discussed in the issue thread with the maintainers, this strict validation approach was chosen over silently falling back to a purely topological network mode. This prevents masking potential bugs in the user's data generation code where they might mistakenly expect spatial queries to work for dropped nodes.

@github-actions
Copy link
Copy Markdown

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔵 +1.4% [+0.7%, +2.1%] 🟢 -4.0% [-4.6%, -3.5%]
BoltzmannWealth large 🔵 +2.4% [+1.5%, +3.3%] 🔵 +3.7% [+2.8%, +4.8%]
Schelling small 🔵 +1.0% [+0.5%, +1.5%] 🔵 +0.9% [+0.7%, +1.1%]
Schelling large 🔵 +1.5% [+0.7%, +2.4%] 🔴 +6.5% [+4.1%, +8.6%]
WolfSheep small 🔵 -0.1% [-0.6%, +0.4%] 🔵 -0.0% [-0.2%, +0.2%]
WolfSheep large 🔵 -1.1% [-2.1%, -0.3%] 🔵 -2.3% [-3.3%, -1.4%]
BoidFlockers small 🔵 -1.7% [-2.1%, -1.4%] 🔵 -1.0% [-1.2%, -0.8%]
BoidFlockers large 🔵 -1.9% [-2.1%, -1.7%] 🔵 -1.2% [-1.4%, -1.0%]

# Create cells and gather KD-Tree data simultaneously
for node_id in self.G.nodes:
pos = np.array(node_positions.get(node_id))
raw_pos = node_positions.get(node_id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it not make more sense to use:

Suggested change
raw_pos = node_positions.get(node_id)
try:
raw_pos = node_positions[node_id]
except KeyError as e:
raise SpaceException() from e

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Copy Markdown
Member

@quaquel quaquel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me with 1 question/suggestion.

@Nithurshen Nithurshen requested a review from quaquel February 26, 2026 15:51
@quaquel quaquel merged commit e1bad5b into mesa:main Mar 2, 2026
12 of 14 checks passed
@Nithurshen Nithurshen deleted the fix-network-layout-validation-3385 branch March 2, 2026 10:00
@EwoutH EwoutH added the bug Release notes label label Mar 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Network initialization crashes when layout dictionary is missing node positions

3 participants