Skip to content

Bug: Unhandled json.JSONDecodeError in new_game and offer_draw Views #338

@divya-d510

Description

@divya-d510

Description

The new_game and offer_draw API endpoints do not handle malformed JSON request bodies.
Sending invalid JSON causes an unhandled json.JSONDecodeError exception, resulting in a
500 Internal Server Error instead of a proper error response.

This is inconsistent with other views in the same file (make_move, set_pause) which
already wrap json.loads() in a try/except block.

Affected views in game/views.py:

  • new_gamedata = json.loads(request.body or '{}')
  • offer_drawdata = json.loads(request.body or '{}')

Steps to Reproduce

  1. Start the Django development server
  2. Send a POST request to /api/new-game/ with a malformed JSON body:
curl -X POST http://localhost:8000/api/new-game/ \
  -H "Content-Type: application/json" \
  -d '{bad json'
  1. Observe the response — a 500 error is returned
  2. Repeat with /api/draw/ using the same malformed body

Expected Behavior

The API should return a 400 Bad Request response with a descriptive error message:

{
  "error": "Invalid JSON."
}

No server crash or 500 error should occur.

Actual Behavior

The server raises an unhandled json.JSONDecodeError and returns a 500 Internal Server Error.
In production (with DEBUG = False), this exposes no detail to the client but still represents
a crash. In development, a full traceback is shown:

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Screenshots

N/A — API/backend issue, reproducible via curl or Postman.

Additional Context

The fix is straightforward — wrap the json.loads() call in both affected views with a
try/except block, exactly as already done in make_move:

# Current (vulnerable) code in new_game and offer_draw:
data = json.loads(request.body or '{}')

# Fix — consistent with make_move view:
try:
    data = json.loads(request.body or '{}')
except json.JSONDecodeError:
    return JsonResponse({'error': 'Invalid JSON.'}, status=400)

This brings both views in line with the existing error-handling pattern used elsewhere
in game/views.py.

Metadata

Metadata

Assignees

Labels

GSSoCUnder GirlScript Summer of CodebugSomething isn't workinggood first issueGood for newcomers

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions