Skip to content

Bug: workflow expression ordering comparisons return False for non-numeric strings #3321

Description

@Quratulain-bilal

summary

in the workflow expression evaluator, ordering comparisons (<, >, <=, >=) between non-numeric strings silently return False. dates, version tags, and names never compare correctly.

root cause

_safe_compare in src/specify_cli/workflows/expressions.py coerces both operands to a number before comparing:

try:
    if isinstance(left, str):
        left = float(left) if "." in left else int(left)
    if isinstance(right, str):
        right = float(right) if "." in right else int(right)
except (ValueError, TypeError):
    return False

any non-numeric string fails int()/float(), hits the except, and returns False for the whole comparison. so a legitimate string ordering is lost.

reproduction

from specify_cli.workflows.expressions import evaluate_expression
from specify_cli.workflows.base import StepContext

ctx = StepContext(inputs={"d": "2026-01-01"})
# want True (jan is before feb); actual: False
evaluate_expression("{{ inputs.d < '2026-02-01' }}", ctx)

ctx = StepContext(inputs={"name": "beta"})
# want True; actual: False
evaluate_expression("{{ inputs.name > 'alpha' }}", ctx)

==/!= are unaffected (they don't go through _safe_compare); only ordering ops.

impact

any workflow when: / gate condition that orders strings — comparing an iso date, a semver-ish tag, or a name — evaluates as False regardless of the real order, so steps are skipped (or run) incorrectly with no error.

proposed fix

coerce to a number only when both operands look numeric; otherwise compare the original values. two strings then order lexicographically like python, two numeric strings still compare as numbers ("10" > "9"), and a number vs a non-numeric string stays incomparable (False).

happy to open a PR (have one ready with a regression test).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions