Search code examples
pythoncerberus

RuntimeError: There's no handler for [insert_filed_name] in the 'validate' domain


I am using cerberus v1.3.2 with python-3.8 stable to validate json data that will be used to send http requests. I am having an issue using the dependencies rule. My objects have a field request_type and an optional field payload that contains more data. Only objects that have a request_type in ['CREATE', 'AMEND'] have a payload. When I run the validation, I get an error related to one of the fields in payload. Here is the code I'm running:

from cerberus import Validator

request = {
    "request_type": "CREATE",
    "other_field_1": "whatever",
    "other_field_2": "whatever",
    "payload": {
        "id": "123456",
        "jobs": [
            {
                "duration": 1800,
                "other_field_1": "whatever",
                "other_field_2": "whatever"
            }
        ]
    }
}

schema = {
    'request_type': {
        'type': 'string',
        'allowed': ['CREATE', 'CANCEL', 'AMEND'],
        'required': True,
        'empty': False
    },
    'other_field_1': {'type': 'string', },
    'other_field_2': {'type': 'string', },
    'payload': {
        'required': False,
        'schema': {
            'id': {
                'type': 'string',
                'regex': r'[A-Za-z0-9_-]`',
                'minlength': 1, 'maxlength': 32,
                'coerce': str
            },
            'jobs': {
                'type': 'list',
                'schema': {
                    'duration': {
                        'type': 'integer', 'min': 0,
                        'required': True, 'empty': False,
                    },
                    'other_field_1': {'type': 'string', },
                    'other_field_2': {'type': 'string', },
                }
            }
        },
        'dependencies': {'request_type': ['CREATE', 'AMEND']},
    }
}

validator = Validator(schema, purge_unknown=True)
if validator.validate(request):
    print('The request is valid.')
else:
    print(f'The request failed validation: {validator.errors}')

And this is the error I'm getting:

"RuntimeError: There's no handler for 'duration' in the 'validate' domain."

Is there something I'm doing wrong?

For context, I managed to make the validation work by using the exact same rules, but instead of using dependencies, I have two separate schemas named payload_schema and no_payload_schema. In payload_schema I set the allowed values for request_type to ['CREATE', 'AMEND'], and in no_payload_schema I set the allowed values to ['CANCEL']. I run the validation on both schemas and if neither of them passes, I raise an error. This sounds a bit hacky and I'd like to understand how I could use the dependencies rule to do that.


Solution

  • Mind the difference between schema being used for mappings and sequences. The jobs field's value won't be checked as mapping since you require it to be of list type. You'll need this pattern:

    {"jobs": 
      {
        {"type": "list", "schema": 
          {
            "type": "dict", "schema": {"duration": ...}
          }
        }
      }
    }
    

    This ambiguity of the schema rule will be addressed in the next major release of Cerberus. For the sake of readability one may use schema- and rule set-registries with complex validation schemas.

    It is generally advisable to ask with minimum examples for support.