Перейти к содержанию

Смарт-действия — Известные проблемы

Документ — реестр известных проблем и ограничений смарт-действий (Smart Actions) 1Формы: активные ограничения (локализация ФИО в CreateUser/UpdateUser, EventID 64 в WhenOpenTask, Lua-ориентированная справка редактора при любом языке скрипта) и ранее исправленные проблемы. Для инженеров поддержки и разработчиков, работающих с пакетами смарт-действий.


1. CreateUser / UpdateUser не поддерживают локализованные ФИО

Статус: исправлено

Симптом: при создании пользователя через смарт-действие «Создать пользователя» нельзя указать ФИО на дополнительном языке (например, английском). ФИО записывается как локализация только для языка, указанного в параметре «Язык».

Причина: действие записывает локализованное ФИО только для основного языка пользователя; параметров для второго языка нет.

Решение: в действиях «Создать пользователя» и «Обновить пользователя» добавлены параметры «Фамилия (локализованная)», «Имя (локализованное)», «Отчество (локализованное)» и «Язык локализации» — ФИО на дополнительном языке задаётся штатно. См. actions-reference-people.md. Ограничение касается только одного действия: при обычном сохранении карточки пользователя локализованные ФИО распространяются на языки-автокопии — см. Локализация — бизнес-правила.


2. WhenOpenTask (EventID 64) срабатывает в SPA только в представлении «Чаты»

Статус: ограничение подтверждено, поведение намеренное

Симптом: смарт-правило на событие «Во время открытия задачи» не срабатывает, когда пользователь открывает задачу в стандартной карточке (полное представление). Срабатывает только при открытии в представлении «Чаты».

Обходной путь: событие можно вызвать напрямую через API (POST /api/v2/tasks/{taskId}/when-open-task) — без ограничений по представлению. Актуально для интеграций и мобильного клиента.

Дополнительно: контекст открытия передаётся в @eventParam1 (не @eventParam0). @eventParam0 у данного события не используется — нетипичное поведение по сравнению с другими событиями.


3–6. Исправленные ранее проблемы (сборки 2.268.63 – 2.268 «Скульптор»)

Четыре исправленные ранее проблемы с указанием сборок исправления; в текущих сборках не воспроизводятся.

Mustache-шаблоны возвращали пустые строки (исправлено в 2.268.77): смарт-действие «Сгенерировать файл по шаблону» с mustache-шаблоном возвращало пустое содержимое.

Смарт-отмена (Cancel) в Lua не работала (исправлено в 2.268.63): действие «Отменить» (Cancel) не отрабатывало корректно при вызове из Lua-скрипта.

Ошибка 500 на смарт-кнопках действий (исправлено в 2.268.74): ошибка при нажатии на смарт-кнопки действий (в частности, при генерации файла по шаблону).

HTML-таблица с числовыми отступами обрывала формирование файла по шаблону (исправлено в 2.268 «Скульптор»): значение с <table cellspacing="0"> или <table cellpadding="0"> приводило к ошибке The input string '"0"' was not in a correct format и отказу действия «Сгенерировать по шаблону». Теперь такие значения формируются так же, как записанные с обычными кавычками.


6. ESQL: FROM {0} без алиаса — 500 на reserved keyword

Статус: исправлено

Симптом: запросы вида SELECT VALUE COUNT(1) FROM {0} WHERE ... возвращают 500. Проявлялось при вычислении видимости блоков смарт-фильтра в МТФ.

Причина: в бесконтекстной ветке генератора ESQL конструкция FROM {0} подставлялась без алиаса коллекции. Парсер ESQL принимал стоящий сразу за FROM reserved keyword (WHERE, ORDER, GROUP) за имя коллекции. В контекстной ветке (FROM Tasks as t) алиас присутствовал, поэтому ошибка не воспроизводилась.

Инвариант: алиас as t подставляется во всех ветках генератора ESQL.

7. Потеря значения параметра действия через admin-MCP (JsonElement)

Статус: исправлено

Симптом: при сохранении действия пакета через admin-MCP (/mcp-admin-api-actions-pack-editor → actions_pack_editor_save_pack_action) значение параметра не записывалось в БД. Проявлялось двумя способами: - ArgumentException: unknown value type: System.Text.Json.JsonElement — значение не распознавалось контролом параметра. - SqlException 547 — нарушение CHECK-ограничения CK_PacksActionsParameters_Value_XOR_Expression при вставке параметра с пустым значением.

Причина: admin-MCP десериализует тело запроса через System.Text.Json, помещая в object-поле FixedValue тип JsonElement. Базовый класс контролов ParameterControlBase обрабатывал только JObject (Newtonsoft) и нативные типы — JsonElement попадал в else-ветку с исключением. Отдельно — отсутствие фильтрации пустых параметров в MergeParameters позволяло довести до БД строку с пустыми значениями всех источников.

Инвариант: ParameterControlBase.SerializeValue обрабатывает JsonElement наравне с JObject; PacksActionsEntityService.MergeParameters фильтрует параметры без значения через HasParameterValue перед записью.

8. CreateUser / UpdateUser: поле «Пароль» в редакторе всегда пустое, отдельной очистки нет

Симптом: в редакторе пакета действий поле «Пароль» действий «Создать пользователя» и «Изменить пользователя» всегда отображается пустым, даже если пароль был задан ранее. Отдельного способа очистить ранее сохранённый пароль в интерфейсе нет.

Причина: значение пароля хранится в зашифрованном виде и намеренно не возвращается в редактор, в описание действия и в экспорт модуля — поле работает только на запись. Пустое поле при сохранении трактуется как «не менять сохранённое значение».

Обходной путь: чтобы заменить пароль, введите новое значение. Чтобы убрать ранее сохранённый пароль, смените источник значения параметра (выражение, скрипт или предопределённый параметр) либо пересоздайте действие.

9. Невалидный JSON в значении параметра действия пакета — 500 вместо ошибки ввода

Статус: исправлено

Симптом: сохранение действия пакета со значением параметра, структура которого не соответствует контролу — например, у элемента выбора пользователей идентификатор пустой, — отвечало HTTP 500, а в журнал исключений писалась ошибка десериализации Error converting value {null} to type 'System.Int32'. Path 'users[0].id'.

Причина: в ParameterControlBase.TryParseNaive десериализация входного значения — JsonElement.Deserialize<TV> для запросов от admin-MCP и JObject.ToObject<TV>() для запросов от SPA — выполнялась без перехвата: исключение уходило наверх мимо фильтра, который переводит логические ошибки в 400.

Решение: блок десериализации обёрнут в try/catch, перехватывающий System.Text.Json.JsonException, Newtonsoft.Json.JsonException, InvalidCastException и ArgumentException, и вместо них бросается TCLogicException с сообщением «некорректное значение параметра действия» — фильтр API транслирует её в HTTP 400. Поведение наследуют все контролы на базе ParameterControlBase<TV>; разбор корректных значений не изменился.

10. Справка в редакторе смарт-скриптов всегда Lua-ориентированная

Симптом: в скрипте на языке, отличном от Lua (Python, JavaScript, OneScript, C#), кнопка «i» («Библиотека подсказок») открывает окно с заголовком «Помощь по lua-скриптам» и содержимым про Lua: RESULT, CONTEXT как объект задачи/пользователя/письма, var_dump, is_empty, вкладка «Смарт-действия». В Python и остальных языках эти имена и конструкции не работают.

Причина: справка — единый текст из ресурсов интерфейса (ключи luaDoc.* словаря common). Язык скрипта в компонент справки не передаётся, переключение её содержания по языку не реализовано; кнопка выводится в тулбаре независимо от языка, а заголовок берётся из ресурса common.helpWithLuaScripts.

Обходной путь: штатного переключателя справки нет. Для Python ориентир — python-scripting.md: ключи ctx, возврат результата, ограничения песочницы; для остальных языков — документы домена по соответствующему языку.

11. Правило «После смены ДП» из другого правила читало значение параметра до изменения

Статус: исправлено

Симптом: правило на событие «После смены ДП», запущенное смарт-действием другого правила, в смарт-выражении получало прежнее значение изменённого параметра — и при чтении из денормализованной таблицы категории, и из значений параметров. Тот же результат давало сохранение пачки параметров одной операцией.

Причина: смарт-выражение выполнялось под отдельной строкой подключения, в собственной сессии базы, и не видело записи, сделанной смарт-действием внутри текущей операции: запись оставалась незафиксированной до её конца.

Решение: признак «читать основной строкой подключения внутри текущей транзакции» удерживается на самой транзакции — при сохранении значения параметра и при сохранении пачки транзакция помечается, и смарт-выражение внутри неё читает записанное значение. Вне таких операций поведение не изменилось. Вошло в сборку 2.268 «Скульптор».

12. «Время ожидания выполнения истекло» по смарт-выражению при сохранении факта

Статус: исправлено в 2.268 «Скульптор»

Симптом: при сохранении трудозатрат с каскадом на проект в журнале ошибок появляются записи о таймауте смарт-выражения, а значение параметра проекта считается по старым данным; пользователь повторяет сохранение.

Причина: выражение в режиме XML-формулы при заданной отдельной строке подключения для смарт-выражений считалось вне транзакции запроса и в другой сессии базы. При уровне изоляции соединения из пула выше «повторяемого чтения» оно ожидало блокировку, которую держала транзакция самого запроса, — отсюда таймаут; при более слабом уровне виден был устаревший результат.

Исправлено. На MS SQL выражение в режиме XML-формулы считается в транзакции вызвавшего запроса и в его сессии, поэтому видит записанное в этой же транзакции. Выражения с собственным T-SQL под отдельной строкой подключения и поведение на PostgreSQL не менялись.

Обходной путь (на сборках до исправления): нет; записи о таймауте по сохранению факта на исправленной сборке не воспроизводятся. Если симптом остался — проверить, что у выражения нет собственного T-SQL, и уточнить сборку площадки.

13. Подсказка типа результата действия «Распаковать» расходилась с рантайм-типом при пропущенных записях

Статус: исправлено (сборка 2.268 «Скульптор»)

Симптом: в редакторе смарт-скриптов у действия «Распаковать» подсказка результата показывала int[]; если в архиве были повреждённые записи или записи, пропущенные по лимитам, скрипт получал объект с полями fileIds и skippedEntries, и штатные приёмы работы с массивом (#, ipairs, table.insert) на нём не работали. Смарт-выражение последующего действия, ссылавшееся на результат разархивации, падало с ошибкой Entity SQL.

Причина: действие объявляет ResultType = int[], а при пропущенных записях возвращает UnzipArchiveResult; в параметр смарт-выражения значение попадало без приведения к массиву.

Исправлено. Подсказка в редакторе показывает обе формы — int[] | { fileIds (int[], 1..n), skippedEntries (string[], 1..n) }, значение UnzipArchiveResult на границе Lua отдаётся таблицей, а в параметр смарт-выражения передаётся массив идентификаторов распакованных файлов. Подробности о форме результата — в справочнике действий, раздел «Файлы (расширение)».

Обходной путь: нет. Признак старого поведения — подсказка результата у действия «Распаковать» показывает только int[], а при пропущенных записях скрипт получает объект.

Связанные документы:

14. «Экспортировать данные в Excel»: выгрузка падает на вычисляемых текстовых колонках

Статус: в работе

Симптом: действие отказывает с текстом Column '<имя колонки>' is read only, файл не создаётся. На PostgreSQL так ведёт себя любая функция с текстовой колонкой; на MS SQL — процедура, у которой строковая колонка получена выражением: склейкой строк, CASE, ISNULL, литералом, параметром процедуры или CAST/CONVERT.

Причина: после перевода вызова на общий доступ к базе результат читается в таблицу данных, и драйвер помечает колонки-выражения как нередактируемые. Генератор файла переписывает текстовые ячейки (срезает HTML-разметку, обрезает краевые пробелы), а запись в такую колонку запрещена. До перевода результат читался способом, который этот признак не выставлял, и те же процедуры выгружались.

Обходной путь: выбирать в процедуре колонки из таблиц и табличных переменных — они остаются редактируемыми. Текст, собираемый выражением, формировать на стороне пакета либо отдельными действиями.

Когда обращаться в поддержку 1Ф: если процедура отдаёт только колонки из таблиц и отказ всё равно воспроизводится — приложить версию площадки, текст ошибки из журнала ошибок платформы и текст процедуры.

15. «Экспортировать данные в Excel»: ошибка после второго набора не останавливает действие

Статус: в работе

Симптом: процедура на MS SQL вернула два и более набора и упала после второго (RAISERROR уровня 11 и выше, THROW, ошибка выполнения) — действие завершается успешно, в задачу вкладывается файл с данными первого набора, в журнале ошибок записи нет, пакет идёт дальше. При откате транзакции внутри процедуры изменения откатываются, а файл с данными отменённого расчёта остаётся в задаче.

Причина: чтение останавливается на первом наборе с колонками; остаток ответа дочитывается при закрытии соединения, а ошибка этой части при закрытии не поднимается. На PostgreSQL проблема не проявляется: функция, завершившаяся ошибкой, строк не отдаёт и вызов падает целиком.

Обходной путь: не держать в одной процедуре с выгрузкой инструкции, способные упасть после выборки, — вынести их отдельным действием пакета либо перестроить процедуру так, чтобы она падала до возврата данных.

Когда обращаться в поддержку 1Ф: при подозрении на частичные данные в приложенном файле — приложить версию площадки и текст процедуры: по журналу пакета такой отказ не виден.

16. Пользовательские смарт-действия не загрузились — редактор пакета отдаёт ошибку или пустой список

Статус: исправлено в 2.268 «Скульптор»

Симптом: после сбоя загрузки пользовательских действий обращение к смарт-действию по идентификатору пользовательского действия отдавало NullReferenceException — в интерфейсе и в фоновых заданиях; каталог доступных типов действий в редакторе пакета отдавал ошибку с пустым списком вместо стандартных групп; предварительная загрузка пользовательских действий не сообщала о сбое.

Причина: реестр пользовательских (кастомных) действий загружается лениво и один раз на процесс — сканером подключённых сборок. При сбое загрузки геттер реестра перехватывал исключение, писал его в лог и возвращал «пустое значение», а потребители разыменовывали его без проверки: строгие — падали, списочный — терял уже собранный список стандартных действий.

Исправлено. Сбой загрузки больше не маскируется: он записывается в журнал ошибок платформы и возвращается как управляемая ошибка «Загрузка пользовательских действий не удалась» с исходной причиной внутри. Обращение по идентификатору пользовательского действия даёт эту управляемую ошибку; каталог имён в редакторе пакета возвращает стандартные действия и не ломается; предварительная загрузка возвращает признак «пользовательские действия не загружены». Стандартные действия и безопасное разрешение имени действия работают как раньше.

Обходной путь: нет. Признак старого поведения — в редакторе пакета не видно ни одного пользовательского действия (либо открывается ошибка), а в журнале ошибок платформы лежит запись о сбое загрузки пользовательских действий. На исправленной сборке в редакторе остаются стандартные группы действий.

Когда обращаться в поддержку 1Ф: если на исправленной сборке пропадают и стандартные действия либо сбой повторяется после перезапуска пула приложения — приложить версию площадки и текст записи из журнала ошибок платформы.

17. «Отправить системный email» без почтового ящика падал разыменованием вместо ошибки конфигурации

Статус: исправлено в 2.268 «Скульптор»

Симптом: пакет с действием «Отправить системный email» (SendMailBoxEmail, ID 44) при незаполненном параметре «Email отправителя» завершался технической ошибкой — NullReferenceException, а при ящике без идентификатора — InvalidOperationException — вместо сообщения о незаполненном параметре. Проявлялось в раздельной рассылке (параметр «Каждому адресату отдельное письмо»).

Причина: в ветке раздельной отправки ящик читался без проверки — mailBox.MailBoxId.Value в TCClassLib/Smart/Actions/ActionsInfoProvider.Methods.cs, при том что отсутствие ящика выше допускалось.

Исправлено. Проверка ящика и его идентификатора выполняется один раз до ветвления — if (mailBox?.MailBoxId == null) в SendMailBoxEmail; при пустом ящике действие отдаёт ошибку конфигурации с указанием «Email отправителя». Отправка с заданным ящиком — и раздельная, и общая — не изменилась; общая отправка без ящика тоже стала возвращать ошибку конфигурации — это принятое расширение поведения, а не прежний сценарий.

Обходной путь: нет. На сборках до исправления раздельная отправка без ящика отвечает технической ошибкой.

Когда обращаться в поддержку 1Ф: если на исправленной сборке отправка с корректно заданным ящиком завершается ошибкой конфигурации — приложить версию площадки, имя пакета и текст ошибки из журнала пакета.


18. Тип контекста смарт-скрипта затирался сохранением

Статус: исправлено в 2.268 «Скульптор»

Симптом: после переименования, публикации или сохранения кода скрипт терял контекст — CONTEXT оказывался пустым, хотя раньше скрипт с задачей работал. Тип мог «прыгать»: один и тот же скрипт в тесте редактора выполнялся то с контекстом, то без.

Причина: тип контекста нигде не задавался явно и доезжал из адреса редактора. При открытии скрипта из действия пакета в адресе стоял тип «задача», и бэкенд подменял им значение из базы — любое сохранение записывало «задача» независимо от того, что было в скрипте, а обновление по API без поля типа записывало «без контекста».

Решение: у существующего скрипта тип всегда берётся из базы и меняется только отдельным вызовом смены типа; адрес редактора и обычное сохранение тип не трогают. См. Редактор смарт-скриптов.

Обходной путь на сборках до исправления: не пересохранять скрипт из действия пакета; тип деплоить по API вместе с полем типа в DTO.

19. Пакет по событию откатывал все итерации списочного действия вместе со сбойной

Статус: исправлено в 2.268 «Скульптор»

Симптом: правило «После изменения значения параметра» проставляло значения по списку, но при сбое одного элемента не сохранялось ни одного: список откатывался целиком, запись о выполнении действия в журнале автоматизации тоже исчезала, а в журнале ошибок оставалась только ошибка итерации. Тот же пакет, запущенный переходом по маршруту, сохранял остальные элементы.

Причина: пакет, запущенный событием внутри транзакции, подтверждал свою область только при полном успехе. Одна отклонённая или сбойная итерация делала пакет неуспешным, и объемлющая операция завершалась без фиксации.

Решение: событийный запуск пакета со списочным действием изолирует сбойную итерацию — её записи откатываются, а записи успешных итераций и запись в журнале автоматизации сохраняются после фиксации объемлющей операции. Поведение прямого запуска пакета, запуск вне транзакции и пакеты без сбоев не изменились; сбой вне итераций списка по-прежнему откатывает пакет целиком. См. Типичные проблемы действий пакета, раздел 4.2.

Обходной путь на сборках до исправления: вынести правило из «После изменения значения параметра» на событие, выполняемое вне операции (например, «После перехода»), либо разбить список на короткие пакеты.