# Agents.jl periodic=true still gives space extent errors

**URL:** https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605
**Category:** General Usage
**Tags:** package, agents
**Created:** [December 17, 2025, 2:09am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605 "2025-12-17T02:09:34Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![BananaMaster3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bananamaster3/32/218457_2.png) [@BananaMaster3](https://discourse.julialang.org/u/BananaMaster3)
#### Post date: [December 17, 2025, 2:09am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/1 "2025-12-17T02:09:34Z")

</div>

Hey all, I have a continuous, periodic space ABM. My ABM declaration looks like this:

```julia-auto
    space2d = ContinuousSpace(extent;
                              periodic=true,
                              );
    model = AgentBasedModel(Particle, space2d;
                            agent_step! = agent_step!,
                            model_step! = (args...) -> (@timeit to "model_step!" model_step!(args...; to=to)),
                            properties=Dict(:attraction_matrix => properties, :time_scale => 1.0, :hitbox => 1.0, :viscosity => 0.9, :max_distance => 80.0)
                            )

```

However running this for a sufficient amount of steps results in this error:

```julia-auto
Error in callback:
position is outside space extent!
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:44
  [2] move_agent!(agent::Main.ParticleLife.Particle, pos::StaticArraysCore.SVector{2, Float64}, model::Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG})
    @ Agents ~/.julia/packages/Agents/WuWeG/src/spaces/continuous.jl:153
  [3] walk!(agent::Main.ParticleLife.Particle, direction::StaticArraysCore.SVector{2, Float64}, model::Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG})
    @ Agents ~/.julia/packages/Agents/WuWeG/src/spaces/walk.jl:64
  [4] move_agent!(agent::Main.ParticleLife.Particle, model::Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG}, dt::Float64)
    @ Agents ~/.julia/packages/Agents/WuWeG/src/spaces/continuous.jl:187
  [5] agent_step!(agent::Main.ParticleLife.Particle, model::Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG})
    @ Main.ParticleLife ~/Documents/Programming/particle-life/particle.jl:115
  [6] step_ahead!(model::Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG}, agent_step!::typeof(Main.ParticleLife.agent_step!), model_step!::Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, n::Int64, t::Base.RefValue{Int64})
    @ Agents ~/.julia/packages/Agents/WuWeG/src/simulations/step_standard.jl:17
  [7] step!
    @ ~/.julia/packages/Agents/WuWeG/src/simulations/step_standard.jl:5 [inlined]
  [8] step!(abmobs::Agents.ABMObservable{Observables.Observable{Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG}}, Nothing, Nothing, Nothing, Nothing, Bool, Observables.Observable{Int64}, Observables.Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}, t::Int64)
    @ AgentsVisualizations ~/.julia/packages/Agents/WuWeG/ext/AgentsVisualizations/src/model_observable.jl:37
  [9] (::AgentsVisualizations.var"#add_controls!##2#add_controls!##3"{Agents.ABMObservable{Observables.Observable{Agents.StandardABM{Agents.ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, Main.ParticleLife.Particle, Dict{Int64, Main.ParticleLife.Particle}, Tuple{DataType}, typeof(Main.ParticleLife.agent_step!), Main.ParticleLife.var"#make_model##0#make_model##1"{TimerOutputs.TimerOutput}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.TaskLocalRNG}}, Nothing, Nothing, Nothing, Nothing, Bool, Observables.Observable{Int64}, Observables.Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}, Observables.Observable{Any}})(c::Int64)
    @ AgentsVisualizations ~/.julia/packages/Agents/WuWeG/ext/AgentsVisualizations/src/interaction.jl:47
 [10] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [11] setindex!(observable::Observables.Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123
 [12] (::Makie.var"#initialize_block!##179#initialize_block!##180"{Makie.Button})(::Makie.MouseEvent)
    @ Makie ~/.julia/packages/Makie/FUAHr/src/makielayout/blocks/button.jl:72
 [13] (::Makie.var"#1313#1314"{Makie.var"#initialize_block!##179#initialize_block!##180"{Makie.Button}})(event::Makie.MouseEvent)
    @ Makie ~/.julia/packages/Makie/FUAHr/src/makielayout/mousestatemachine.jl:94
 [14] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [15] setindex!
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123 [inlined]
 [16] (::Makie.var"#_addmouseevents!##2#_addmouseevents!##3"{Makie.Scene, Base.RefValue{Bool}, Base.RefValue{Union{Nothing, Makie.Mouse.Button}}, Base.RefValue{Float64}, Base.RefValue{Float64}, Base.RefValue{Bool}, Base.RefValue{GeometryBasics.Point{2, Float64}}, Base.RefValue{Bool}, Base.RefValue{Union{Nothing, Makie.Mouse.Button}}, Base.RefValue{Bool}, Base.RefValue{GeometryBasics.Point{2, Float32}}, Base.RefValue{GeometryBasics.Point{2, Float64}}, Base.RefValue{Makie.Mouse.Action}, Observables.Observable{Makie.MouseEvent}, Float64, Module})(event::Makie.MouseButtonEvent)
    @ Makie ~/.julia/packages/Makie/FUAHr/src/makielayout/mousestatemachine.jl:365
 [17] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [18] setindex!
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123 [inlined]
 [19] (::GLMakie.var"#mousebuttons#mousebuttons##0"{Observables.Observable{Makie.MouseButtonEvent}})(window::GLFW.Window, button::GLFW.MouseButton, action::GLFW.Action, mods::Int32)
    @ GLMakie ~/.julia/packages/GLMakie/1dQSN/src/events.jl:104
 [20] _MouseButtonCallbackWrapper(window::GLFW.Window, button::GLFW.MouseButton, action::GLFW.Action, mods::Int32)
    @ GLFW ~/.julia/packages/GLFW/Zwulj/src/callback.jl:46
 [21] macro expansion
    @ ~/.julia/packages/GLFW/Zwulj/src/GLFW.jl:34 [inlined]
 [22] PollEvents
    @ ~/.julia/packages/GLFW/Zwulj/src/glfw3.jl:753 [inlined]
 [23] pollevents(screen::GLMakie.Screen{GLFW.Window}, frame_state::Makie.TickState)
    @ GLMakie ~/.julia/packages/GLMakie/1dQSN/src/screen.jl:546
 [24] on_demand_renderloop(screen::GLMakie.Screen{GLFW.Window})
    @ GLMakie ~/.julia/packages/GLMakie/1dQSN/src/screen.jl:1038
 [25] renderloop(screen::GLMakie.Screen{GLFW.Window})
    @ GLMakie ~/.julia/packages/GLMakie/1dQSN/src/screen.jl:1066
 [26] (::GLMakie.var"#start_renderloop!##0#start_renderloop!##1"{GLMakie.Screen{GLFW.Window}})()
    @ GLMakie ~/.julia/packages/GLMakie/1dQSN/src/screen.jl:927

```

I’m very confused by this. From what I understand, a periodic space lets the agents loop around from one edge to another. I’m pretty sure that this error message, however, is saying that the agent did not loop around, it instead exceeded the space boundaries.

What am I missing?  
Thanks in advance!

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [December 17, 2025, 11:49am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/2 "2025-12-17T11:49:39Z")

</div>

Impossible to say without your stepping function, but my guess is you manually move the agent outside the space boundaries. You should use only the API functions for moving agents. How do you move agents in your model?

---

<div class="post-metadata">

### Author: ![BananaMaster3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bananamaster3/32/218457_2.png) [@BananaMaster3](https://discourse.julialang.org/u/BananaMaster3)
#### Post date: [December 18, 2025, 2:57am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/3 "2025-12-18T02:57:10Z")

</div>

In model\_step, my code updates each particle’s velocity (like `a.vel = ...`). In agent\_step, it uses `move_agent`. Specifically:

```julia-auto
function agent_step!(agent, model)
    move_agent!(agent, model, abmproperties(model)[:time_scale])
end

```

---

<div class="post-metadata">

### Author: ![simonsteiger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonsteiger/32/209862_2.png) [@simonsteiger](https://discourse.julialang.org/u/simonsteiger)
#### Post date: [December 18, 2025, 7:32am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/4 "2025-12-18T07:32:03Z")

</div>

I ran into the same error once when some cells of the forcefield I used to update agent velocities were `NaN`. Agents ending up on these fields were technically still inside the space boundaries in my case but the error thrown was also `position is outside space extent!`.

I can’t say of course, but maybe something similar is happening in your model?

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [December 18, 2025, 10:54am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/5 "2025-12-18T10:54:28Z")

</div>

The way you do it is correct from an API point of view, this function respects periodic spaces. Unfortunatley I cannot help more without a Minimal Working Example.

---

<div class="post-metadata">

### Author: ![BananaMaster3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bananamaster3/32/218457_2.png) [@BananaMaster3](https://discourse.julialang.org/u/BananaMaster3)
#### Post date: [December 21, 2025, 1:38am UTC](https://discourse.julialang.org/t/agents-jl-periodic-true-still-gives-space-extent-errors/134605/6 "2025-12-21T01:38:15Z")

</div>

I figured it out. In case it helps anybody else: my velocity code was dividing by zero, creating a velocity that was equal to [NaN, NaN].
