4

I don't know if this matters, but I'm actually using flask-restplus extension.

All of my other flask error handlers work as expected, but for some reason when handling a marshmallow ValidationError, the response is just my original request body, instead of the marshmallow error message. I've done some debugging and I know that the error handler is being called, and that attributes of the ValidationError are accessible (e.g. verified that error.messages is {'age': ['Missing data for required field.']}).

Has anyone experienced this before? Thanks for reading, and thanks in advance for any help!

The payload:

{"name": "Bob"}

The error handler:

from marshmallow.exceptions import ValidationError

@api.errorhandler(ValidationError)
def marshmallow_error_handler(error):
    # print(error.messages) results in expected {'age': ['Missing data for required field.']}
    return error.messages, 400

The schema:

class SimpleSchema(Schema):
    name = fields.String(required=True)
    age = fields.String(required=True)

Simple route to test handler:

@api.route("/test")
class MarshmallowTest(Resource):
    def post(self):
        SimpleSchema().load(api.payload)

Expected response:

{'age': ['Missing data for required field.']}

Actual response:

{"name": "Bob"}

I've been able to work around this by overriding marshmallow.Schema's handle_error function and raising a custom exception, but I'm still quite curious what's causing this behavior!

LRH
  • 43
  • 1
  • 5

2 Answers2

3

I ran into this error as well and found this Github issue https://github.com/noirbizarre/flask-restplus/issues/530

The workaround I went with is overwriting the data property of the exception in my own handler

    @api.errorhandler(Exception)
    def handle_unexpected_within_restx(e):
        app.logger.exception(e)
        
        data = compose_error_response(e.messages)
        # https://github.com/noirbizarre/flask-restplus/issues/530
        e.data = data
        return data, 400
Dharman
  • 30,962
  • 25
  • 85
  • 135
ken4z
  • 1,340
  • 1
  • 11
  • 18
2

I think that conventional way is to return dict with the 'message' attribute. In my case I put all data from 'messages' as a string

from flask import Flask, json
from marshmallow.exceptions import ValidationError

app = Flask(__name__)

@app.errorhandler(ValidationError)
def register_validation_error(error):
  rv = dict({'message': json.dumps(error.messages)})
  return rv, 422
RomanK
  • 111
  • 1
  • 8