# FAQ: Lua pcall + SMART:execute_action — какие ошибки перехватываются

Документ отвечает на вопросы администраторов и разработчиков о том, какие ошибки `SMART:execute_action` перехватываются конструкцией `pcall`, а какие — нет, и как правильно обрабатывать ошибки в Lua-скриптах. Типичные жалобы: «Обернул `SMART:execute_action("CreateTask", ...)` в `pcall`, но ошибка не ловится», «Lua-скрипт падает с необработанным исключением, хотя стоит `pcall`», «Как правильно обрабатывать ошибки при создании задач из Lua?»

## Как работает перехват ошибок pcall

Конструкция `pcall` оборачивает вызов `SMART:execute_action`. Ошибки, возникшие **при выполнении** действия на стороне платформы, перехватываются и возвращаются в `pcall` как сообщение об ошибке. Ошибки **до запуска** (компиляция скрипта, преобразование параметров) до `pcall` не доходят.

Ошибки, которые `pcall` успешно перехватывает:

| Тип ошибки | Пример | pcall ловит? |
|-----------|--------|:------:|
| Ошибка в пользовательском Lua-коде | `nil + 1`, обращение к nil-полю | ✅ |
| Неверное имя действия | `execute_action("НесуществующееДействие", ...)` | ✅ |
| Неверный тип контекста | `execute_action("CreateTask", id, "unknown", ...)` | ✅ |
| Ошибка бизнес-логики при выполнении действия | Валидация ДП, отсутствие прав | ✅ |
| SQL-ошибки в `SQL:query()`, `SQL:scalar()` | Синтаксическая ошибка в запросе | ✅ |
| Ошибка при выполнении действия | Исключение в процессе выполнения действия | ✅ |

Ошибки, которые `pcall` не перехватывает:

| Тип ошибки | Причина | pcall ловит? |
|-----------|---------|:------:|
| Синтаксическая ошибка Lua | Ошибка при компиляции, до выполнения | ❌ |
| Ошибка преобразования параметров | Невозможность конвертации типов на границе Lua↔C# | ❌ |
| Системное исключение среды (.NET 9) | Исключение возникает до входа в обёртку перехвата | ❌ |
| Ошибки в обработчиках исключений | Если само сохранение исключения в Lua state падает | ❌ |

В .NET 9 изменилось поведение проброса исключений из движка Lua: системное исключение могло «терять» исходное сообщение. В текущих версиях 1Формы это компенсируется на стороне платформы — исходное сообщение об ошибке восстанавливается и доходит до `pcall`.

## Паттерн обработки ошибок и асинхронные вызовы

Рекомендуемый подход — оборачивать вызов в `pcall` и проверять флаг успеха:

```lua
local success, result = pcall(function()
    return SMART:execute_action("CreateTask", nil, "task", {
        SubcatID = 123,
        TaskName = "Новая задача",
        -- ...параметры...
    })
end)

if not success then
    -- result содержит строку с сообщением об ошибке
    print("Ошибка создания задачи: " .. tostring(result))
    -- Можно записать в лог или выполнить альтернативное действие
else
    -- result содержит возвращённое значение (например, ID созданной задачи)
    print("Задача создана: " .. tostring(result))
end
```

Асинхронные вызовы (`async = true`) — особый случай: `execute_action` возвращает `nil` немедленно, ошибки происходят позже в фоне, `pcall` не перехватывает асинхронные ошибки. Для контроля используйте синхронный режим или проверяйте результат отдельно. Учитывайте и момент старта: если скрипт выполняется внутри открытой транзакции, фоновое действие стартует не в момент вызова `execute_action(..., true)`, а после успешной фиксации этой транзакции; при её откате фоновое действие не выполняется вовсе. К моменту, когда исключение из фона попадёт в журнал, данные, по которым оно считало, могут быть уже зафиксированы — или отсутствовать, если запустившая транзакция откатилась.

## Частые причины «pcall не ловит» и отладка

Почему `pcall` может не поймать ошибку и что делать:

| Ситуация | Объяснение | Решение |
|----------|-----------|---------|
| Синтаксическая ошибка в скрипте | Скрипт не компилируется → pcall не вызывается | Исправить синтаксис, проверить в тест-кейсах |
| Ошибка в коде ВНЕ pcall | Исключение до/после блока pcall | Обернуть весь код в pcall |
| Неверный тип параметра | Не удаётся преобразовать тип → системное исключение | Привести типы явно: `tonumber()`, `tostring()` |
| Ошибка при async=true | Асинхронная ошибка не возвращается в pcall | Использовать синхронный вызов для отладки и учитывать, что фон стартует после фиксации транзакции скрипта |

Тест-кейсы смарт-выражений (`SmartExpressionTestCases` в БД) позволяют тестировать Lua-скрипты: задать набор входных параметров, запустить скрипт в безопасном контексте, увидеть полный вывод (print) и исключения. API: `GET /admin/smart/recurrences/execute/{id}` — ручной запуск для проверки.

## Разбор проблем и обращение в поддержку

Для разбора проблемы понадобятся: полный текст Lua-скрипта, сообщение об ошибке (из логов или интерфейса), ID задачи / категории, в контексте которой запускался скрипт, версия платформы (важно для .NET 9).

Когда обращаться в поддержку 1Ф:

- Если `pcall` действительно не ловит ошибку внутри `SMART:execute_action` — возможная проблема среды, обратитесь в поддержку 1Ф
- Если ошибка при компиляции скрипта — проверьте синтаксис
- Если ошибка в бизнес-логике действия — проверьте настройки категории и ДП

Смежные разделы: [Справочник смарт-действий](https://help.1forma.ru/domains/smart-actions/actions-reference.md) — все действия и их параметры; [Смарт-действия — администрирование](https://help.1forma.ru/domains/smart-actions/admin.md).
