Skip to main content

Error Code Overview

The Blackjack API uses specific error codes to identify different types of errors. Each error code is returned in the code field of the error response.

Domain Exception Errors

These errors are thrown by the domain layer when business rules are violated.

GAME_NOT_FOUND

HTTP Status: 404 Not Found
Exception Class: GameNotFoundException
Source: domain/exception/GameNotFoundException.java:4

Description

Thrown when attempting to access a game that doesn’t exist in the system.

When It Occurs

  • Retrieving game state with an invalid game ID
  • Playing a move on a non-existent game
  • Deleting a game that doesn’t exist

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 404,
  "code": "GAME_NOT_FOUND",
  "message": "Game not found: abc123",
  "path": "/api/v1/games/abc123"
}

Usage in Code

// Thrown in GetGameStateUseCase.java:22
gameRepository.findById(gameId)
    .switchIfEmpty(Mono.error(new GameNotFoundException(gameId)))

PLAYER_NOT_FOUND

HTTP Status: 404 Not Found
Exception Class: PlayerNotFoundException
Source: domain/exception/PlayerNotFoundException.java:4

Description

Thrown when attempting to access a player that doesn’t exist in the system.

When It Occurs

  • Changing the name of a non-existent player
  • Retrieving player information with an invalid player ID
  • Accessing player statistics or game history

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 404,
  "code": "PLAYER_NOT_FOUND",
  "message": "Player not found: player123",
  "path": "/api/v1/players/player123"
}

Usage in Code

// Thrown in ChangePlayerNameUseCase.java:32
playerRepository.findById(playerId)
    .switchIfEmpty(Mono.error(new PlayerNotFoundException(cmd.playerId())))

INVALID_PLAYER_NAME

HTTP Status: 400 Bad Request
Exception Class: InvalidPlayerNameException
Source: domain/exception/InvalidPlayerNameException.java:4

Description

Thrown when a player name violates validation rules.

Validation Rules

  • Cannot be null
  • Cannot be blank (empty or whitespace only)
  • Maximum length: 30 characters
  • Leading/trailing whitespace is trimmed

When It Occurs

  • Creating a new game with an invalid player name
  • Changing a player’s name to an invalid value

Example Responses

Empty Name:
{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 400,
  "code": "INVALID_PLAYER_NAME",
  "message": "PlayerName cannot be blank",
  "path": "/api/v1/games"
}
Name Too Long:
{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 400,
  "code": "INVALID_PLAYER_NAME",
  "message": "PlayerName too long (max 30)",
  "path": "/api/v1/players/123/name"
}

Usage in Code

// Thrown in CreateNewGameUseCase.java:27
try {
    playerName = new PlayerName(cmd.playerName());
} catch (IllegalArgumentException e) {
    return Mono.error(new InvalidPlayerNameException(e.getMessage()));
}

INVALID_MOVE

HTTP Status: 409 Conflict
Exception Class: InvalidMoveException
Source: domain/exception/InvalidMoveException.java:4

Description

Thrown when attempting to perform a game move that is not allowed in the current game state.

When It Occurs

  • Playing a move (HIT or STAND) when the game is not in progress
  • Attempting to play after the game has finished
  • Trying to make moves on a game that’s in PLAYER_WINS, DEALER_WINS, or PUSH status

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 409,
  "code": "INVALID_MOVE",
  "message": "Game is not in progress",
  "path": "/api/v1/games/abc123/move"
}

Usage in Code

// Thrown in Game.java:111
private void ensureInProgress() {
    if (status != GameStatus.IN_PROGRESS) 
        throw new InvalidMoveException("Game is not in progress");
}

Validation Errors

VALIDATION_ERROR

HTTP Status: 400 Bad Request
Exception Classes: WebExchangeBindException, ConstraintViolationException
Source: GlobalExceptionHandler.java:67, GlobalExceptionHandler.java:81

Description

Thrown when request data fails Spring validation constraints.

When It Occurs

  • Missing required fields in request body
  • Invalid data types
  • Constraint violations on DTOs
  • Bean validation failures

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 400,
  "code": "VALIDATION_ERROR",
  "message": "playerName: must not be blank; action: must not be null",
  "path": "/api/v1/games/abc123/move"
}

General Errors

BAD_REQUEST

HTTP Status: 400 Bad Request
Exception Class: IllegalArgumentException
Source: GlobalExceptionHandler.java:91

Description

Catch-all for illegal arguments and malformed requests.

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 400,
  "code": "BAD_REQUEST",
  "message": "Invalid game action",
  "path": "/api/v1/games/abc123/move"
}

INTERNAL_ERROR

HTTP Status: 500 Internal Server Error
Exception Class: Exception (generic)
Source: GlobalExceptionHandler.java:101

Description

Generic error for unexpected server-side exceptions. The actual error details are logged server-side but a generic message is returned to the client for security.

Example Response

{
  "timestamp": "2024-03-06T10:15:30.123Z",
  "status": 500,
  "code": "INTERNAL_ERROR",
  "message": "Unexpected error",
  "path": "/api/v1/games/abc123"
}

Error Code Summary Table

Error CodeHTTP StatusExceptionCommon Scenarios
GAME_NOT_FOUND404GameNotFoundExceptionInvalid game ID in request
PLAYER_NOT_FOUND404PlayerNotFoundExceptionInvalid player ID in request
INVALID_PLAYER_NAME400InvalidPlayerNameExceptionName validation failure
INVALID_MOVE409InvalidMoveExceptionMove on finished game
VALIDATION_ERROR400WebExchangeBindException, ConstraintViolationExceptionRequest validation failure
BAD_REQUEST400IllegalArgumentExceptionMalformed request
INTERNAL_ERROR500ExceptionUnexpected server error

Handling Errors in Your Application

Check Error Codes

Always check the code field to determine the specific error type:
if (error.code === 'GAME_NOT_FOUND') {
  // Redirect to game list or show "game not found" message
} else if (error.code === 'INVALID_MOVE') {
  // Show user that move is not allowed
}

User-Friendly Messages

The message field contains technical details. Consider mapping error codes to user-friendly messages:
const errorMessages = {
  'GAME_NOT_FOUND': 'This game could not be found. It may have been deleted.',
  'INVALID_MOVE': 'This move is not allowed. The game may have already ended.',
  'INVALID_PLAYER_NAME': 'Please enter a valid player name (1-30 characters).'
};

Logging

Always log the full error response for debugging:
console.error('API Error:', {
  timestamp: error.timestamp,
  code: error.code,
  message: error.message,
  path: error.path
});

Build docs developers (and LLMs) love