{"record":{"id":"48eed9a00a3bf155","repo":"dotnet/orleans","slug":"this-game-is-not-in-play","errorCode":null,"errorMessage":"This game is not in play","messagePattern":"This game is not in play","errorType":"exception","errorClass":"ApplicationException","httpStatus":null,"severity":"error","filePath":"samples/TicTacToe/Grains/GameGrain.cs","lineNumber":72,"sourceCode":"        _playerIds.Add(player);\n\n        // check if the game is ready to play\n        if (_gameState is GameState.AwaitingPlayers && _playerIds.Count is 2)\n        {\n            // a new game is starting\n            _gameState = GameState.InPlay;\n            _indexNextPlayerToMove = Random.Shared.Next(0, 1);  // random as to who has the first move\n        }\n\n        // let user know if game is ready or not\n        return Task.FromResult(_gameState);\n    }\n\n    // make a move during the game\n    public async Task<GameState> MakeMove(GameMove move)\n    {\n        // check if its a legal move to make\n        if (_gameState is not GameState.InPlay) throw new ApplicationException(\"This game is not in play\");\n\n        if (_playerIds.IndexOf(move.PlayerId) < 0) throw new ArgumentException(\"No such playerid for this game\", \"move\");\n        if (move.PlayerId != _playerIds[_indexNextPlayerToMove]) throw new ArgumentException(\"The wrong player tried to make a move\", \"move\");\n\n        if (move.X < 0 || move.X > 2 || move.Y < 0 || move.Y > 2) throw new ArgumentException(\"Bad co-ordinates for a move\", \"move\");\n        if (_board[move.X, move.Y] != -1) throw new ArgumentException(\"That square is not empty\", \"move\");\n\n        // record move\n        _moves.Add(move);\n        _board[move.X, move.Y] = _indexNextPlayerToMove;\n\n        // check for a winning move\n        var win = false;\n        for (var i = 0; i < 3 && !win; i++)\n        {\n            win = IsWinningLine(_board[i, 0], _board[i, 1], _board[i, 2]);\n        }\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/samples/TicTacToe/Grains/GameGrain.cs#L54-L90","documentation":"Thrown by TicTacToe GameGrain.MakeMove when _gameState is not GameState.InPlay — moves are only legal during active play. This is the primary state-machine guard on the move path; it precedes the player/co-ordinate validation checks.","triggerScenarios":"A client calls MakeMove(move) while the game is AwaitingPlayers (fewer than two players) or Finished. The check `if (_gameState is not GameState.InPlay)` fires before any board validation.","commonSituations":"Submitting a move before both players have joined; moving on a game that already has a winner; a race where the second player has not yet triggered the AwaitingPlayers->InPlay transition.","solutions":["Ensure both players have joined (AddPlayerToGame transitions to InPlay at two players) before any move.","Do not move on a Finished game — start a new one.","Have the client track GameState and only call MakeMove when InPlay."],"exampleFix":"// before\nawait game.MakeMove(move); // throws if not InPlay\n\n// after: guard on the client using the returned game state\nif (await game.GetState() != GameState.InPlay) return;\nawait game.MakeMove(move);","handlingStrategy":"validation","validationCode":"// Only move while the game is in play\nif (await game.GetState() != GameState.InPlay) return;\nawait game.MakeMove(move);","typeGuard":"null","tryCatchPattern":"try { await game.MakeMove(move); }\ncatch (ApplicationException ex) when (ex.Message.Contains(\"not in play\"))\n{ /* refresh state, wait for second player */ }","preventionTips":["Ensure both players have joined (transition to InPlay) before moving.","Never move on a Finished game.","Drive the client off the returned GameState rather than assumptions."],"tags":["game","state-machine","validation","sample"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}