Как исправить ошибку [ОшибкаХранимыхДанных] при проведении документа в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

С выходом новых версий платформы 1С:Предприятие (начиная с 8.3.23 и выше) разработчики и администраторы столкнулись с новым типом системных уведомлений. Одно из самых неинформативных на первый взгляд — это исключение с тегом [ОшибкаХранимыхДанных]. Рассмотрим подробнее, почему оно возникает и как найти истинную причину проблемы, когда стандартный отладчик не дает четкого ответа.

Суть проблемы и почему старые методы не работают

Раньше при возникновении ошибки во время записи или проведения объекта система выдавала стандартное сообщение: "Ошибка при вызове метода контекста (Записать)". Теперь же платформа внедряет механизм категоризации. Тег [ОшибкаХранимыхДанных] сообщает нам, что проблема произошла на уровне работы с данными, которые должны быть сохранены в базу (документы, справочники, регистры).

Главная сложность заключается в том, что эта ошибка часто "маскирует" реальную причину. Проанализируем ситуацию: если в коде программы (в модуле объекта, подписке на события или расширении) переменной Отказ присваивается значение Истина, но при этом программист забыл вывести поясняющее сообщение пользователю, платформа выдает этот общий заполнитель. Чтобы минимизировать количество таких «немых» ошибок в будущем, рекомендуется использовать статический анализатор кода проектов еще на этапе разработки — для этого подойдёт набор инструментов разработчика и аналитика для 1С.

Поиск скрытого "Отказа" через отладку

Если при попытке проведения документа в режиме отладки с установленной опцией "Остановка по ошибке" конфигуратор останавливается на строке ДокументОбъект.Записать(), но не заходит внутрь обработчиков, разберем по шагам, что нужно проверить. Для экономии времени на перезапусках среды в таких ситуациях удобно использовать специальный помощник отладки — для этого подойдёт инструмент быстрой отладки и анализа кода 1С.

  1. Проверим все обработчики событий, которые срабатывают при записи: ПередЗаписью, ПриЗаписи и ОбработкаПроведения.
  2. Особое внимание уделим подпискам на события. Часто ошибка кроется именно в них, так как они выполняются "неявно". Чтобы не искать их вручную, можно запустить анализ подписок на объекты конфигурации, который покажет все связанные процедуры.
  3. Выясним причину через замер производительности. Включим замер, нажмем кнопку проведения и проанализируем текст модулей, где встречается строка Отказ = Истина.

Рассмотрим пример "плохого" кода, который вызывает подобную неочевидную ошибку:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если ЗначениеЗаполнено(ЭтотОбъект.Контрагент) = Ложь Тогда
        // Программист установил отказ, но не сообщил пользователю причину
        Отказ = Истина; 
    КонецЕсли;
КонецПроцедуры

В новых версиях платформы такой код приведет к появлению окна [ОшибкаХранимыхДанных] без дополнительных подробностей.

Анализ расширений конфигурации

Как показывает практика, наиболее часто проблема скрывается в расширениях. Платформа 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. Выгрузите объект в XML до попытки проведения.
  2. В отладчике, в самом конце процедуры ОбработкаПроведения, принудительно установите Отказ = Ложь (если платформа позволяет завершить выполнение) и выгрузите результат в XML повторно.
  3. Сравните два файла. Это поможет увидеть, какие именно движения или реквизиты заполняются некорректно, вызывая конфликт с логикой базы данных.

Резюме и рекомендации

Выясним главную причину: появление [ОшибкаХранимыхДанных] — это сигнал разработчику о том, что в конфигурации или расширении происходит "тихий" отказ. Платформа 1С 8.3.23+ стала более требовательна к качеству кода обработки ошибок.

Для предотвращения подобных ситуаций в будущем:

← На главную