Workflow Query Error Handling

Developer guide for the Enezaframework workflow engine. Part of the Workflow series.

Table of Contents

  1. Overview
  2. parse_annotations() Validation Errors
  3. Django-Level Errors
  4. Workflow Engine Errors
  5. 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"]