С выходом новых версий платформы 1С:Предприятие (начиная с 8.3.23 и выше) разработчики и администраторы столкнулись с новым типом системных уведомлений. Одно из самых неинформативных на первый взгляд — это исключение с тегом [ОшибкаХранимыхДанных]. Рассмотрим подробнее, почему оно возникает и как найти истинную причину проблемы, когда стандартный отладчик не дает четкого ответа.
Раньше при возникновении ошибки во время записи или проведения объекта система выдавала стандартное сообщение: "Ошибка при вызове метода контекста (Записать)". Теперь же платформа внедряет механизм категоризации. Тег [ОшибкаХранимыхДанных] сообщает нам, что проблема произошла на уровне работы с данными, которые должны быть сохранены в базу (документы, справочники, регистры).
Главная сложность заключается в том, что эта ошибка часто "маскирует" реальную причину. Проанализируем ситуацию: если в коде программы (в модуле объекта, подписке на события или расширении) переменной Отказ присваивается значение Истина, но при этом программист забыл вывести поясняющее сообщение пользователю, платформа выдает этот общий заполнитель. Чтобы минимизировать количество таких «немых» ошибок в будущем, рекомендуется использовать статический анализатор кода проектов еще на этапе разработки — для этого подойдёт набор инструментов разработчика и аналитика для 1С.
Если при попытке проведения документа в режиме отладки с установленной опцией "Остановка по ошибке" конфигуратор останавливается на строке ДокументОбъект.Записать(), но не заходит внутрь обработчиков, разберем по шагам, что нужно проверить. Для экономии времени на перезапусках среды в таких ситуациях удобно использовать специальный помощник отладки — для этого подойдёт инструмент быстрой отладки и анализа кода 1С.
ПередЗаписью, ПриЗаписи и ОбработкаПроведения.Отказ = Истина.Рассмотрим пример "плохого" кода, который вызывает подобную неочевидную ошибку:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЗначениеЗаполнено(ЭтотОбъект.Контрагент) = Ложь Тогда
// Программист установил отказ, но не сообщил пользователю причину
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
В новых версиях платформы такой код приведет к появлению окна [ОшибкаХранимыхДанных] без дополнительных подробностей.
Как показывает практика, наиболее часто проблема скрывается в расширениях. Платформа 8.3.23 изменила логику проброса исключений из расширений. Если в расширении используется аннотация &Вместо, &Перед или &После и там происходит логическая ошибка или принудительная установка отказа, это может вызвать общее системное сообщение.
В этом случае полезно провести комплексный анализ состава расширений на наличие ошибок, связанных с вызовами экспортных процедур и функций. Нам необходимо выполнить глобальный поиск по всем расширениям строки Отказ = Истина. Если вы нашли место, где устанавливается Отказ, добавьте туда вывод сообщения, чтобы локализовать проблему:
&После("ОбработкаПроведения")
Процедура Расш1_ОбработкаПроведения(Отказ, РежимПроведения)
Если Не ПроверитьОстаткиНаСкладе() Тогда
Отказ = Истина;
// Добавьте это сообщение, чтобы расшифровать [ОшибкаХранимыхДанных]
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Недостаточно остатков по данным расширения контроля!";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
Если отладчик и замер производительности не помогают (например, ошибка происходит на стороне СУБД или глубоко в ядре платформы), воспользуемся самым мощным инструментом — Технологическим журналом (удобно через панель анализа технологического журнала и СУБД). Нам нужно настроить сбор событий EXCP (исключительные ситуации).
Пример файла настроек logcfg.xml для отлова этой ошибки:
<config xmlns="http://v8.1c.ru/7.4/config/log">
<log location="C:\Logs\1C_Errors" history="24">
<event>
<eq property="Name" value="EXCP"/>
</event>
<property name="all"/>
</log>
</config>
После воспроизведения ошибки в логах ТЖ можно будет найти полный текст ошибки. Чтобы упростить чтение полученных логов, можно убрать лишние переносы строк в событиях технологического журнала, что сделает анализ данных от SQL-сервера гораздо удобнее. Часто там обнаруживаются проблемы с уникальностью номеров или превышением длины строк в полях таблиц.
Рассмотрим еще один интересный метод диагностики, предложенный опытными разработчиками. Если документ не проводится, но вы не понимаете, что именно меняется в его данных:
ОбработкаПроведения, принудительно установите Отказ = Ложь (если платформа позволяет завершить выполнение) и выгрузите результат в XML повторно.Выясним главную причину: появление [ОшибкаХранимыхДанных] — это сигнал разработчику о том, что в конфигурации или расширении происходит "тихий" отказ. Платформа 1С 8.3.23+ стала более требовательна к качеству кода обработки ошибок.
Для предотвращения подобных ситуаций в будущем:
Отказ = Истина выводом информативного сообщения для пользователя.&Вместо.