A model has no idea what bad input looks like. If a field is missing or null, the empty cell makes the model raise an error and the client gets a 500, as if your server broke. If a field is true, pandas reads it as the number 1, and the client gets a real-looking prediction for a customer nobody described. A wrong answer with a 200 is the worst kind: nobody notices it.
The fix is to validate the body before the model sees it, and answer 400 Bad Request naming the field to fix. data.get(name) gives None for a missing key instead of raising, and type() gives a value's exact type. That matters for True, which Python counts as an int:
print(type(110.5) in (int, float)) # True
print(type("4") in (int, float)) # False: a string
print(type(None) in (int, float)) # False: missing or null
print(isinstance(True, int)) # True!
print(type(True) in (int, float)) # False: its type is bool
Check the fields in the order of COLUMNS and stop at the first one that fails. Your finished route must answer:
POST /predict {"customer_id": 42, "returned_item": 0, "days_since_last": 40, "spent": 160, "orders": 3, "visits": 7}
→ 200 {"bought_again": 1, "probability": 0.701}
POST /predict {"visits": 7, "orders": 3, "days_since_last": 40, "returned_item": 0}
→ 400 {"error": "Missing or not a number", "field": "spent"}
POST /predict {"visits": "twelve", "orders": 4, "spent": 260, "days_since_last": 15, "returned_item": 0}
→ 400 {"error": "Missing or not a number", "field": "visits"}
POST /predict {"visits": true, "orders": 4, "spent": 260, "days_since_last": 15, "returned_item": 0}
→ 400 {"error": "Missing or not a number", "field": "visits"}
POST /predict {"visits": 10, "orders": "4", "spent": 260, "days_since_last": 15, "returned_item": 0}
→ 400 {"error": "Missing or not a number", "field": "orders"}
POST /predict {"visits": 10, "orders": 4, "spent": 260, "days_since_last": null, "returned_item": 0}
→ 400 {"error": "Missing or not a number", "field": "days_since_last"}
POST /predict {"visits": 7, "orders": 2, "spent": 110.5, "days_since_last": 60, "returned_item": 0}
→ 200 {"bought_again": 1, "probability": 0.536}
Your task: in predict, right after the data line, check every name in COLUMNS: if its value is missing or isn't exactly an int or a float, answer 400 with {"error": "Missing or not a number", "field": name}.
Assignment
Follow the Coding Tutorial to check every field of the body before the model sees it.
Hint
A return inside the loop ends the function at the first bad field. Return jsonify(...), a comma, then 400 to set the status.
Free plan: 30 tutor messages. PRO is unlimited.
