Skip to content

Commit 5a440cb

Browse files
authored
Handle exceptions like GenerativeAIPromptError in UI (baserow#4368)
1 parent aec1ced commit 5a440cb

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

backend/src/baserow/contrib/database/ws/rows/signals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def rows_ai_values_generation_error(
131131
"row_ids": [row.id for row in rows],
132132
"error": error_message,
133133
},
134-
getattr(user, "web_socket_id", None),
134+
None,
135135
table_id=table.id,
136136
)
137137
)

backend/tests/baserow/contrib/database/ws/test_ws_rows_signals.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from rest_framework import serializers
1010
from rest_framework.fields import Field
1111

12+
from baserow.contrib.database.rows import signals as row_signals
1213
from baserow.contrib.database.rows.actions import UpdateRowsActionType
1314
from baserow.contrib.database.rows.handler import RowHandler
1415
from baserow.contrib.database.rows.registries import (
@@ -383,3 +384,62 @@ def test_rows_history_updated(
383384
mock_broadcast_many_channel_group.mock_calls == row_history_many_broadcast_calls
384385
)
385386
assert mock_broadcast_channel_group.mock_calls == table_and_row_broadcast_calls
387+
388+
389+
@pytest.mark.django_db(transaction=True)
390+
@patch("baserow.ws.registries.broadcast_to_channel_group")
391+
def test_rows_ai_values_generation_error(mock_broadcast_to_channel_group, data_fixture):
392+
user = data_fixture.create_user()
393+
table = data_fixture.create_database_table(user=user)
394+
field = data_fixture.create_text_field(table=table)
395+
model = table.get_model()
396+
row1 = model.objects.create()
397+
row2 = model.objects.create()
398+
399+
row_signals.rows_ai_values_generation_error.send(
400+
sender=None,
401+
user=user,
402+
rows=[row1, row2],
403+
field=field,
404+
table=table,
405+
error_message="Test error message",
406+
)
407+
408+
mock_broadcast_to_channel_group.delay.assert_called_once()
409+
args = mock_broadcast_to_channel_group.delay.call_args
410+
assert args[0][0] == f"table-{table.id}"
411+
assert args[0][1]["type"] == "rows_ai_values_generation_error"
412+
assert args[0][1]["table_id"] == table.id
413+
assert args[0][1]["field_id"] == field.id
414+
assert args[0][1]["row_ids"] == [row1.id, row2.id]
415+
assert args[0][1]["error"] == "Test error message"
416+
assert args[0][2] is None
417+
418+
419+
@pytest.mark.django_db(transaction=True)
420+
@patch("baserow.ws.registries.broadcast_to_channel_group")
421+
def test_rows_ai_values_generation_error_with_empty_rows(
422+
mock_broadcast_to_channel_group, data_fixture
423+
):
424+
user = data_fixture.create_user()
425+
table = data_fixture.create_database_table(user=user)
426+
field = data_fixture.create_text_field(table=table)
427+
428+
row_signals.rows_ai_values_generation_error.send(
429+
sender=None,
430+
user=user,
431+
rows=[],
432+
field=field,
433+
table=table,
434+
error_message="Model not available",
435+
)
436+
437+
mock_broadcast_to_channel_group.delay.assert_called_once()
438+
args = mock_broadcast_to_channel_group.delay.call_args
439+
assert args[0][0] == f"table-{table.id}"
440+
assert args[0][1]["type"] == "rows_ai_values_generation_error"
441+
assert args[0][1]["table_id"] == table.id
442+
assert args[0][1]["field_id"] == field.id
443+
assert args[0][1]["row_ids"] == []
444+
assert args[0][1]["error"] == "Model not available"
445+
assert args[0][2] is None
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "bug",
3+
"message": "Handle exceptions like GenerativeAIPromptError in UI",
4+
"issue_origin": "github",
5+
"issue_number": 4350,
6+
"domain": "database",
7+
"bullet_points": [],
8+
"created_at": "2025-12-01"
9+
}

web-frontend/modules/database/store/view/grid.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,14 @@ export const mutations = {
738738
Vue.delete(state.pendingFieldOps, key)
739739
})
740740
},
741+
CLEAR_ALL_PENDING_FIELD_OPERATIONS_FOR_FIELD(state, { fieldId }) {
742+
const keysToDelete = Object.keys(state.pendingFieldOps).filter(
743+
(key) => state.pendingFieldOps[key][0] === fieldId
744+
)
745+
keysToDelete.forEach((key) => {
746+
Vue.delete(state.pendingFieldOps, key)
747+
})
748+
},
741749
UPDATE_ROW_HEIGHT(state, value) {
742750
state.rowHeight = value
743751
},
@@ -3471,7 +3479,12 @@ export const actions = {
34713479
commit('SET_PENDING_FIELD_OPERATIONS', { fieldId, rowIds, value })
34723480
},
34733481
AIValuesGenerationError({ commit, dispatch }, { fieldId, rowIds }) {
3474-
commit('SET_PENDING_FIELD_OPERATIONS', { fieldId, rowIds, value: false })
3482+
// If rowIds is empty, clear ALL pending operations for this field.
3483+
if (rowIds.length === 0) {
3484+
commit('CLEAR_ALL_PENDING_FIELD_OPERATIONS_FOR_FIELD', { fieldId })
3485+
} else {
3486+
commit('SET_PENDING_FIELD_OPERATIONS', { fieldId, rowIds, value: false })
3487+
}
34753488
dispatch(
34763489
'toast/error',
34773490
{

0 commit comments

Comments
 (0)