Skip to content

Commit e240757

Browse files
authored
fix: harden BaserowIndex evaluation against unaugmented args (baserow#5321)
`BaserowIndex.to_django_expression_given_args` assumed that `type_function_given_valid_args` had already augmented every call from 2 to 4 arguments by appending the array sub-type's mode and SQL template literals. When the augmentation has not run, accessing args[2]/args[3] raises `IndexError: list index out of range` and breaks endpoints that evaluate the formula (row create/update/delete, batch operations, and application-builder dispatch). Fall back to the generic text extraction defaults when fewer than four arguments are present so the function degrades gracefully instead of 500ing. Fixes baserow#5320 / Sentry BASEROW-SAAS-BACKEND-GT
1 parent e087e71 commit e240757

3 files changed

Lines changed: 39 additions & 2 deletions

File tree

backend/src/baserow/contrib/database/formula/ast/function_defs.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3107,8 +3107,12 @@ def to_django_expression_given_args(
31073107
args: List["WrappedExpressionWithMetadata"],
31083108
context: BaserowExpressionContext,
31093109
) -> "WrappedExpressionWithMetadata":
3110-
mode = _unwrap_literal_value(args[2].expression) or "text"
3111-
value_sql = _unwrap_literal_value(args[3].expression) or "{elem} ->> 'value'"
3110+
# Fall back to text defaults if args weren't augmented at type time.
3111+
mode = "text"
3112+
value_sql = "{elem} ->> 'value'"
3113+
if len(args) >= 4:
3114+
mode = _unwrap_literal_value(args[2].expression) or mode
3115+
value_sql = _unwrap_literal_value(args[3].expression) or value_sql
31123116
safe_index = handle_arg_being_nan(
31133117
args[1].expression,
31143118
Value(None, output_field=fields.IntegerField()),

backend/tests/baserow/contrib/database/formula/test_index_generalized.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,3 +864,27 @@ def test_index_nan_argument_returns_null(data_fixture):
864864
result = model.objects.get(id=row_a.id)
865865
assert getattr(result, nan_field.db_column) is None
866866
assert getattr(result, div_zero_field.db_column) is None
867+
868+
869+
def test_baserow_index_to_django_expression_handles_unaugmented_args():
870+
"""Regression test: https://github.com/baserow/baserow/issues/5320"""
871+
872+
from django.db.models import IntegerField, JSONField, Value
873+
874+
from baserow.contrib.database.formula.ast.function_defs import BaserowIndex
875+
from baserow.contrib.database.formula.expression_generator.django_expressions import (
876+
JSONBArrayGetElement,
877+
)
878+
from baserow.contrib.database.formula.expression_generator.generator import (
879+
WrappedExpressionWithMetadata,
880+
)
881+
882+
array_arg = WrappedExpressionWithMetadata(Value([], output_field=JSONField()))
883+
index_arg = WrappedExpressionWithMetadata(Value(0, output_field=IntegerField()))
884+
885+
result = BaserowIndex().to_django_expression_given_args(
886+
[array_arg, index_arg], context=None
887+
)
888+
889+
assert isinstance(result, WrappedExpressionWithMetadata)
890+
assert isinstance(result.expression, JSONBArrayGetElement)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "bug",
3+
"message": "Fixed index(), first() and last() formulas crashing on partial arguments.",
4+
"issue_origin": "github",
5+
"issue_number": 5320,
6+
"domain": "database",
7+
"bullet_points": [],
8+
"created_at": "2026-05-06"
9+
}

0 commit comments

Comments
 (0)