При разработке механизмов обмена данными или автоматизированной загрузки объектов в 1С:Предприятие программисты часто сталкиваются с ситуацией, когда метод Записать() не срабатывает, но стандартные средства отлова ошибок не дают информации о причинах сбоя. В этой статье мы подробно разберем, почему конструкция Попытка...Исключение в связке с ОписаниеОшибки() может подвести, и как правильно извлечь текст ошибки, возникшей в обработчике ПередЗаписью или при проверке уникальности.
Рассмотрим типичную ситуацию: вы выполняете запись объекта (например, справочника Номенклатура) в блоке исключения. Если запись прерывается, управление передается в блок Исключение, однако функция ОписаниеОшибки() не содержит привычного текста (например, сообщения о неуникальности номера или незаполненном реквизите).
Выясним причину такого поведения платформы. В 1С существует разделение между системными исключениями (критическими ошибками кода, падением сервера, нарушением прав доступа) и логическим отказом от записи. Когда в обработчике ПередЗаписью параметру Отказ присваивается значение Истина, или когда встроенные механизмы платформы (контроль уникальности, проверка заполнения) блокируют запись:
Исключение.Именно поэтому ОписаниеОшибки() оказывается пустым — с точки зрения системы критического сбоя не произошло, произошел штатный программный отказ.
Для того чтобы «выловить» текст ошибки, который платформа или другой разработчик вывели через объект СообщениеПользователю, нам необходимо обратиться к очереди сообщений. Разберем по шагам, как модифицировать код записи для корректного логирования.
Проанализируем пример кода, который позволит собрать все сообщения, возникшие в процессе неудачной попытки записи:
Попытка
ТекстОшибки = "";
СпрОбъект.Записать();
Исключение
// 1. Пытаемся получить системное описание (на случай ошибки кода)
ТекстОшибки = ОписаниеОшибки();
// 2. Извлекаем сообщения, накопленные платформой
МассивСообщений = ПолучитьСообщенияПользователю(Истина);
Для Каждого Сообщение Из МассивСообщений Цикл
ТекстОшибки = ТекстОшибки + Символы.ПС + Сообщение.Текст;
КонецЦикла;
// 3. Записываем результат в лог (Журнал регистрации)
Если ЗначениеЗаполнено(ТекстОшибки) Тогда
ЗаписьЖурналаРегистрации("ЗагрузкаДанных.ОшибкаЗаписи",
УровеньЖурналаРегистрации.Ошибка,
СпрОбъект.Метаданные(),
СпрОбъект.Ссылка,
"Не удалось записать объект: " + ТекстОшибки);
КонецЕсли;
КонецПопытки;
Посмотрим подробнее на параметры используемых функций. Метод ПолучитьСообщенияПользователю(Истина) принимает булево значение. Параметр Истина критически важен: он означает, что после получения сообщений они будут удалены из очереди. Если вы не очистите очередь, сообщения будут выведены пользователю стандартным окном сообщений 1С после завершения серверного вызова, что может привести к дублированию информации или путанице в интерфейсе.
Также стоит обратить внимание на объект СообщениеПользователю. Каждый элемент массива, возвращаемого функцией, содержит не только свойство Текст, но и данные о том, к какому полю или объекту относится ошибка. Если ваша цель — детальный лог, вы можете извлекать свойства ПутьКДанным и Поле.
Проанализируем ситуацию с контролем уникальности. Если у справочника в метаданных стоит галочка «Контроль уникальности», платформа сама проверяет код или другие реквизиты перед фиксацией транзакции. В случае нарушения уникальности:
Записать() прерывается.ПолучитьСообщенияПользователю().Поэтому предложенное решение является универсальным как для ошибок, прописанных вручную в модуле объекта, так и для стандартных проверок платформы.
В актуальных версиях платформы 8.3 рекомендуется использовать функцию ИнформацияОбОшибке() вместо ОписаниеОшибки(). Она возвращает объект типа ИнформацияОбОшибке, который содержит структурированные данные о сбое.
Рассмотрим пример расширенного сбора данных:
Исключение
Инфо = ИнформацияОбОшибке();
ТекстЛога = "Краткое описание: " + Инфо.Описание + Символы.ПС;
ТекстЛога = ТекстЛога + "Имя модуля: " + Инфо.ИмяМодуля + ", Строка: " + Инфо.НомерСтроки;
// Добавляем сообщения из очереди
Сообщения = ПолучитьСообщенияПользователю(Истина);
Для Каждого Стр Из Сообщения Цикл
ТекстЛога = ТекстЛога + Символы.ПС + "Сообщение: " + Стр.Текст;
КонецЦикла;
// Запись в Журнал Регистрации
// ...
КонецПопытки;
Важный нюанс: В режиме отладчика значения системных функций типа ОписаниеОшибки() могут отображаться как «неопределено» или «пусто», если вы пытаетесь просмотреть их в табло после того, как контекст исключения был затронут другими операциями. Всегда фиксируйте результат функции в локальную переменную сразу в первой строке блока Исключение.
Таким образом, мы выяснили, что для надежного определения ошибки в обработчике ПередЗаписью недостаточно полагаться на стандартное исключение. Сочетание сбора системной информации и извлечения пользовательских сообщений позволяет получить полную картину произошедшего и обеспечить качественное логирование работы системы.