diff --git a/src/events/character/Move.ts b/src/events/character/Move.ts
index 86f865f..e43f36f 100644
--- a/src/events/character/Move.ts
+++ b/src/events/character/Move.ts
@@ -5,14 +5,12 @@ import prisma from '../../utilities/Prisma'
 import { AStar, type Node } from '../../utilities/Player/AStar'
 import Rotation from '../../utilities/Player/Rotation'
 import { ExtendedCharacter as Character } from '../../utilities/Types'
-import { start } from 'node:repl'
 
 interface SocketResponse {
   position_x: number
   position_y: number
 }
 
-// Map to store movement tokens for each character
 const characterMoveTokens = new Map<number, Symbol>()
 
 export default function setupCharacterMove(socket: TSocket, io: Server) {
@@ -25,19 +23,26 @@ export default function setupCharacterMove(socket: TSocket, io: Server) {
         return
       }
 
-      // Cancel any ongoing movement for this character
+      const oldMoveToken = characterMoveTokens.get(socket.character.id)
+      if (oldMoveToken) {
+        characterMoveTokens.delete(socket.character.id)
+      }
+
       const moveToken = Symbol('moveToken')
       characterMoveTokens.set(socket.character.id, moveToken)
 
       const grid = await ZoneManager.getGrid(socket.character.zoneId)
 
-      if (grid.length === 0) {
-        console.error('character:move error', 'Grid not found')
+      if (!grid || grid.length === 0) {
+        console.error('character:move error', 'Grid not found or empty')
         return
       }
 
-      const start = { x: socket.character.position_x, y: socket.character.position_y }
-      const end = { x: data.position_x, y: data.position_y }
+      const start = { x: Math.floor(socket.character.position_x), y: Math.floor(socket.character.position_y) }
+      const end = { x: Math.floor(data.position_x), y: Math.floor(data.position_y) }
+
+      console.log('Pathfinding from', start, 'to', end)
+      console.log('Grid dimensions:', grid.length, 'x', grid[0].length)
 
       const path = AStar.findPath(start, end, grid)
 
@@ -45,10 +50,10 @@ export default function setupCharacterMove(socket: TSocket, io: Server) {
         socket.character.isMoving = true
         io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
 
-        // Start movement in a non-blocking manner
         moveAlongPath(socket, io, path, grid, moveToken).catch(console.error)
       } else {
         console.log('character:move error', 'No valid path found')
+        socket.emit('character:moveError', 'No valid path found')
       }
     } catch (error) {
       console.error('character:move error', error)
@@ -65,18 +70,23 @@ async function moveAlongPath(socket: TSocket, io: Server, path: Node[], grid: nu
 
   const totalSteps = path.length
   const updateInterval = 50 // milliseconds between updates
-  const totalDuration = totalSteps * 250 // total duration of movement
 
   for (let step = 0; step < totalSteps; step++) {
-    const startTime = Date.now()
+    if (characterMoveTokens.get(socket.character.id) !== moveToken) {
+      console.log('Movement cancelled for character', socket.character.id)
+      return
+    }
 
-    while (Date.now() - startTime < 250) { // 250ms per tile
+    const startTime = Date.now()
+    const stepDuration = 250 // 250ms per tile
+
+    while (Date.now() - startTime < stepDuration) {
       if (characterMoveTokens.get(socket.character.id) !== moveToken) {
         console.log('Movement cancelled for character', socket.character.id)
         return
       }
 
-      const progress = (Date.now() - startTime) / 250
+      const progress = (Date.now() - startTime) / stepDuration
       const currentPosition = interpolatePosition(path[step], path[step + 1] || path[step], progress)
 
       if (isObstacle(currentPosition, grid)) {
@@ -97,8 +107,9 @@ async function moveAlongPath(socket: TSocket, io: Server, path: Node[], grid: nu
     }
   }
 
-  if (socket.character) {
+  if (socket.character && characterMoveTokens.get(socket.character.id) === moveToken) {
     socket.character.isMoving = false
+    characterMoveTokens.delete(socket.character.id)
     io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
   }
 }
diff --git a/src/utilities/Player/AStar.ts b/src/utilities/Player/AStar.ts
index 4df0e92..afb9687 100644
--- a/src/utilities/Player/AStar.ts
+++ b/src/utilities/Player/AStar.ts
@@ -10,9 +10,6 @@ export interface Node extends Position {
   f: number
 }
 
-/**
- * A* pathfinding algorithm.
- */
 export class AStar {
   private static readonly ORTHOGONAL_DIRECTIONS: Position[] = [
     { x: 0, y: -1 }, { x: 0, y: 1 }, { x: -1, y: 0 }, { x: 1, y: 0 }
@@ -22,14 +19,6 @@ export class AStar {
     { x: -1, y: -1 }, { x: -1, y: 1 }, { x: 1, y: -1 }, { x: 1, y: 1 }
   ]
 
-  /**
-   * Finds the shortest path from start to end on the given grid.
-   * @param start - Start position.
-   * @param end - End position.
-   * @param grid - The grid representing the map (0 = open space, 1 = obstacle).
-   * @param allowDiagonal - Whether diagonal movements are allowed.
-   * @returns Array of `Node` representing the path from start to end.
-   */
   static findPath(start: Position, end: Position, grid: number[][], allowDiagonal: boolean = false): Node[] {
     const openList: Node[] = []
     const closedSet = new Set<string>()
@@ -103,8 +92,16 @@ export class AStar {
 
   private static isValidPosition(pos: Position, grid: number[][], end: Position): boolean {
     const { x, y } = pos
-    return x >= 0 && y >= 0 && x < grid.length && y < grid[0].length &&
-      (grid[y][x] === 0 || (x === end.x && y === end.y))
+
+    if (!grid || grid.length === 0 || !Array.isArray(grid[0])) {
+      return false;
+    }
+
+    const height = grid.length;
+    const width = grid[0].length;
+
+    return x >= 0 && x < width && y >= 0 && y < height &&
+      (grid[y][x] === 0 || (x === end.x && y === end.y));
   }
 
   private static isInOpenList(openList: Node[], node: Position): boolean {