Workflow Query Error Handling
Developer guide for the Enezaframework workflow engine. Part of the Workflow series.
Table of Contents
- Overview
parse_annotations()Validation Errors- Django-Level Errors
- Workflow Engine Errors
- Related Guides
Overview
Errors arise at three layers: annotation parsing (ValueError), Django ORM evaluation, and workflow condition evaluation (caught and routed by failure behavior). The earlier the layer, the clearer the message.
flowchart TD
A["parse_annotations()"] -->|bad input| V["ValueError with explicit message"]
A -->|valid| B["annotate + filter"]
B -->|bad alias / PK type| D["Django FieldError / ValueError"]
B -->|ok| C["queryset"]
C --> E["workflow condition evaluation"]
E -->|raises| F["ConditionEvaluationError -> failure behavior"]parse_annotations() Validation Errors
| Condition | Error message |
|---|---|
| Missing required keys | Annotation {...} is missing required keys: 'function', 'field', 'related_model', 'alias' |
| Unsupported function | Unsupported aggregate function 'percentile'. Supported: sum, count, avg, min, max |
| Invalid relationship | 'bad_relation' is not a valid relationship on Invoice. Check the related_model name against FK fields, M2M fields, or reverse relation accessors. |
Sources: enezaworkflowengine/utils.py:222-224, :229-232, :271-274.
Note the missing-keys message is emitted even for count when only field is missing — field is optional for count, so omit the key rather than passing an empty string to avoid ambiguity.
Django-Level Errors
| Condition | Behavior |
|---|---|
object_id does not match the model PK type |
Django raises ValueError; the caller handles it (the detail view captures it into execution_error). |
| Annotations present but no filter rules | Still valid — returns the annotated queryset. |
Old-format JSON with no annotations key |
Backward compatible — no aggregation. |
| Multiple annotations sharing an alias | The last one wins (dict overwrite); this is the caller's responsibility. |
SaveQueryDetailView wraps execution in a try/except and stores the message in context['execution_error'], setting result_count to 0 (views/querybuilder.py:231-248).
Workflow Engine Errors
The workflow engine catches condition-evaluation failures and applies the step's condition_failure_behavior (enezaworkflowengine/models/choices.py:88-91):
| Behavior | Effect |
|---|---|
FAIL_CLOSED |
Route to the if_false branch. |
FAIL_OPEN |
Route to the if_true branch. |
FAIL_ESCALATE |
Halt the workflow. |
The Celery task retrieves the behavior with a default of FAIL_CLOSED when evaluation raises (tasks/workflow_tasks.py:256-260). The exception types are ConditionStepError (from services/condition_step.py:11) and the engine's ConditionEvaluationError.
flowchart TD
EVAL["Evaluate condition"] --> OK{"success?"}
OK -->|Yes| R["true / false branch"]
OK -->|No| B{"condition_failure_behavior"}
B -->|FAIL_CLOSED| F["if_false"]
B -->|FAIL_OPEN| T["if_true"]
B -->|FAIL_ESCALATE| H["Halt workflow"]