Skip to content

Bug: FixedAgent.remove Blocked by Setter #3466

@hillhack

Description

@hillhack

Problem: Conflict Between FixedCell and FixedAgent

The issue arises from a contradiction between how FixedCell enforces immobility and how FixedAgent performs cleanup.

Conflict in cell_agent.py

In FixedCell, the cell setter prevents movement:

@cell.setter
def cell(self, cell: Cell | None) -> None:
    if self._mesa_cell is not None:
        raise ValueError("Cannot move agent in FixedCell")
    cell.add_agent(self)  # Fails if cell is None
    self._mesa_cell = cell

Because this setter blocks reassignment, FixedAgent.remove() bypasses the public API and modifies internal state directly:

def remove(self):
    super().remove()
    self.cell.remove_agent(self)  # Manual cleanup
    self._mesa_cell = None        # Direct private state change

Why This Is a Problem

  1. API Inconsistency
    For a CellAgent, removing the agent is simple:
agent.cell = None

For a FixedAgent, the same operation raises:

ValueError("Cannot move agent in FixedCell")

  1. Fragility

The setter has an additional edge case:

agent.cell = None

If the agent is already None, the setter attempts:

None.add_agent(self)

which raises an error because None has no such method.


  1. Encapsulation Violation

FixedAgent.remove() modifies the private attribute:

self._mesa_cell = None

If a user performs the same action in their model code, they would be breaking encapsulation, yet the framework itself relies on this workaround.


Result

  • Inconsistent agent removal behavior
  • Fragile setter logic
  • Internal reliance on private state manipulation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions