makeplane/plane · error · ValueError

Invalid y_axis value: {y_axis}

Error message

Invalid y_axis value: {y_axis}

What it means

ValueError raised by `build_graph_plot` (analytics_plot.py:76) when `y_axis` is not in `VALID_YAXIS`, which contains exactly two values: `issue_count` and `estimate`. Any other y_axis string (including the UPPERCASE `WORK_ITEM_COUNT` used by build_chart, or typos like `issue_count`) triggers it.

Source

Thrown at apps/api/plane/utils/analytics_plot.py:77

        return queryset, "dimension"
    else:
        return queryset.annotate(dimension=F(x_axis)), "dimension"


def sort_data(data, temp_axis):
    # When the axis is in priority order by
    if temp_axis == "priority":
        order = ["low", "medium", "high", "urgent", "none"]
        return {key: data[key] for key in order if key in data}
    else:
        return dict(sorted(data.items(), key=lambda x: (x[0] == "none", x[0])))


def build_graph_plot(queryset, x_axis, y_axis, segment=None):
    if x_axis not in VALID_ANALYTICS_FIELDS:
        raise ValueError(f"Invalid x_axis value: {x_axis}")
    if y_axis not in VALID_YAXIS:
        raise ValueError(f"Invalid y_axis value: {y_axis}")
    if segment and segment not in VALID_ANALYTICS_FIELDS:
        raise ValueError(f"Invalid segment value: {segment}")

    # temp x_axis
    temp_axis = x_axis
    # Extract the x_axis and queryset
    queryset, x_axis = extract_axis(queryset, x_axis)
    if x_axis == "dimension":
        queryset = queryset.exclude(dimension__isnull=True)

    #
    if segment in ["created_at", "start_date", "target_date", "completed_at"]:
        queryset = annotate_with_monthly_dimension(queryset, segment, "segmented")
        segment = "segmented"

    queryset = queryset.values(x_axis)

    # Issue count

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Pass exactly 'issue_count' or 'estimate' (lowercase) for y_axis.
  2. Do not pass build_chart's 'WORK_ITEM_COUNT' to analytics_plot - translate it to 'issue_count'.
  3. Validate y_axis against VALID_YAXIS before the call in bgtasks/tests.
  4. Confirm the workspace has estimates configured if you pass 'estimate', otherwise the resulting data may be empty.

Example fix

# before
build_graph_plot(qs, x_axis="priority", y_axis="WORK_ITEM_COUNT")
build_graph_plot(qs, x_axis="priority", y_axis="count")

# after
build_graph_plot(qs, x_axis="priority", y_axis="issue_count")
Defensive patterns

Strategy: validation

Validate before calling

from plane.utils.analytics_plot import VALID_YAXIS

def is_valid_y_axis(y_axis: str) -> bool:
    # VALID_YAXIS is exactly ['issue_count', 'estimate']
    return y_axis in VALID_YAXIS

Type guard

from plane.utils.analytics_plot import VALID_YAXIS

def is_valid_y_axis(value: str) -> bool:
    return isinstance(value, str) and value in VALID_YAXIS

Try / catch

try:
    dist = build_graph_plot(qs, x_axis, y_axis, segment)
except ValueError as e:
    if 'Invalid y_axis' in str(e):
        return bad_request(str(e))

Prevention

When it happens

Trigger: Calling build_graph_plot with y_axis other than 'issue_count' or 'estimate'. The HTTP AnalyticsEndpoint guards this and returns 400 first, so the raw ValueError surfaces in the export bgtask or direct internal callers.

Common situations: Mixing the two analytics APIs: build_chart uses UPPERCASE y-axis 'WORK_ITEM_COUNT' while analytics_plot uses lowercase 'issue_count'; passing 'estimate' when the project has no estimate system enabled; typos.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/f6a415747adbe368. Report an issue: GitHub.