stride3d/stride · error · InvalidOperationException
Overlapping update commands
Error message
Overlapping update commands
What it means
PlayerController.TryMove starts an asynchronous pathfinding move and stores state in taskCompletionSource. If a previous move is still in flight (taskCompletionSource not yet cleared), calling TryMove again would overwrite that state, so the library throws this InvalidOperationException to prevent overlapping navigation commands.
Solutions
- Await or observe the Task<MoveResult> from the previous TryMove before issuing a new one.
- Track the in-flight task in a field and skip/requeue new moves while it is not completed.
- Call Reset() (which clears the pending state) before starting a new move if abandoning the current one.
- Ensure the pending move always completes (check MoveResult failures) so taskCompletionSource gets cleared.
Example fix
// before
// in Update()
playerController.TryMove(destination); // every frame while one is pending
// after
if (currentMove == null || currentMove.IsCompleted)
currentMove = await playerController.TryMove(destination); Defensive patterns
Strategy: type-guard
Validate before calling
if (playerController.IsMoving) return; // don't call TryMove while a move is pending
Type guard
bool CanMove(PlayerController pc) => pc.IsMoving == false;
Try / catch
try { await playerController.TryMove(dest); } catch (InvalidOperationException ex) when (ex.Message == "Overlapping update commands") { /* skip or cancel the previous move, then retry */ } Prevention
- Always await the Task returned by TryMove before issuing another move
- Track the in-flight move Task in a field and gate new commands on IsCompleted
- Use Reset() when abandoning an in-flight move
- Avoid issuing TryMove from per-frame Update code without completion checks
When it happens
Trigger: Calling TryMove while a previous TryMove task is still pending (not completed and its completion source not reset), e.g. issuing a new move command every frame without awaiting the returned Task.
Common situations: Calling TryMove in Update() without awaiting/monitoring the previous move result; user input retriggering movement before the character reached the destination; a move task that never completes keeping taskCompletionSource non-null forever.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot receive out of micro-thread context.
- Custom strides is not supported with packed PixelFormats
- Please add a NavigationComponent to the entity containing…
- Please add a CharacterComponent to the entity containing…
- Unable to find the base
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/d7b3d1d8662915c8.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Navigation.Tests/PlayerController.cs:162
Character.SetVelocity(moveDirection * Speed);
}
else
{
// No target
HaltMovement();
}
}
public void UpdateSpawnPosition()
{
Entity.Transform.UpdateWorldMatrix();
SpawnPosition = Entity.Transform.WorldMatrix.TranslationVector;
}
public Task<MoveResult> TryMove(Vector3 destination)
{
if (taskCompletionSource != null)
throw new InvalidOperationException("Overlapping update commands");
pendingResult = new MoveResult();
pendingResult.Start = Entity.Transform.WorldMatrix.TranslationVector;
pendingResult.StartTime = Game.UpdateTime.Total;
pendingResult.Success = false;
// Generate a new path using the navigation component
pathToDestination.Clear();
if (Navigation.TryFindPath(destination, pathToDestination))
{
// Skip the points that are too close to the player
waypointIndex = 0;
while (!ReachedDestination && (CurrentWaypoint - Entity.Transform.WorldMatrix.TranslationVector).Length() < 0.25f)
{
waypointIndex++;
}
// Add destination pointView on GitHub (pinned to 96fad776d2)