Разработка и Конфигурация · 13 мин
Как вызвать исключение в 1С: практическое руководство
Как вызвать исключение в 1С: оператор ВызватьИсключение, конструкция Попытка–Исключение, проброс ошибок, логирование в журнал регистрации и типичные ошибки.
Исключение в 1С — это механизм принудительной остановки выполнения кода при возникновении ошибочной ситуации. Разработчик может как перехватывать системные исключения через конструкцию «Попытка — Исключение», так и самостоятельно генерировать их оператором ВызватьИсключение, когда логика прикладного решения требует прервать операцию: например, при незаполненном обязательном реквизите, ошибке обмена данными или недопустимом состоянии объекта.
Корректное использование исключений отличает устойчивый код от хрупкого: вместо молчаливого продолжения работы с некорректными данными программа останавливается, фиксирует причину и либо передаёт её вызывающему коду, либо показывает пользователю понятное сообщение. При этом важно различать исключения и обычные сообщения пользователю — это разные механизмы с разным назначением.
Ниже разобраны синтаксис оператора, способы получения информации об ошибке, паттерны проброса и перехвата исключений, а также типичные ошибки, которые приводят к потере данных об ошибке или падению транзакций.
Синтаксис оператора ВызватьИсключение
Базовая форма оператора предельно проста: после ключевого слова указывается строка с описанием причины. Как только интерпретатор встречает этот оператор, выполнение текущего кода немедленно прекращается.
Если Не ЗначениеЗаполнено(ДоговорКонтрагента) Тогда
ВызватьИсключение "Не указан договор контрагента. Проведение документа невозможно.";
КонецЕсли;
Текст исключения должен отвечать на два вопроса: что пошло не так и что сделать, чтобы исправить ситуацию. Сообщение вида «Ошибка!» не даёт ни диагностики, ни пути решения и вынуждает разбираться в коде. Хороший текст содержит контекст: имя объекта, значение проблемного параметра, ожидаемое условие.
Оператор можно вызывать без параметров, но только внутри блока Исключение — такой вызов означает повторный проброс текущей ошибки выше по стеку. Вне обработчика вызов без параметра приведёт к системной ошибке.
Перехват исключений: Попытка — Исключение — КонецПопытки
Чтобы ошибка не оборвала выполнение всей операции, потенциально опасный код помещают в блок Попытка. Если внутри него возникает исключение — системное или вызванное вручную — управление переходит в блок Исключение, где ошибку можно проанализировать и обработать.
Попытка
Результат = ВыполнитьОбменДанными(Узел);
Исключение
ИнфоОшибки = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Обмен данными",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнфоОшибки));
Сообщить("Обмен не выполнен: " + КраткоеПредставлениеОшибки(ИнфоОшибки));
КонецПопытки;
Ключевой принцип: блок Исключение не должен быть пустым. Пустой обработчик «проглатывает» ошибку — операция внешне завершается успешно, но данные остаются в непредсказуемом состоянии, а найти причину сбоя становится почти невозможно. Минимальная обработка — запись в журнал регистрации.
Обработчики можно вкладывать друг в друга. Внутренний блок перехватывает ошибки своего фрагмента, внешний — всё, что не было обработано внутри. Это позволяет локализовать обработку: например, ошибку записи одного элемента справочника обработать локально и продолжить цикл, а ошибку соединения с базой — пробросить наверх и прервать всю операцию.
Получение информации об ошибке
Внутри блока Исключение доступны два подхода к получению сведений об ошибке. Классический метод — функция ОписаниеОшибки(), которая возвращает строку с описанием. Современный и более информативный способ — функция ИнформацияОбОшибке(), возвращающая объект со структурированными данными.
Объект информации об ошибке содержит описание, имя модуля, номер строки, исходную строку кода и ссылку на вложенную причину ошибки (свойство Причина), если исключение было обёрнуто в другое. Для формирования текста используют функции КраткоеПредставлениеОшибки() — для сообщения пользователю и ПодробноеПредставлениеОшибки() — для журнала регистрации и диагностики.
| Способ | Что возвращает | Когда применять |
|---|---|---|
ОписаниеОшибки() | Строка с описанием ошибки | Простые случаи, поддержка старого кода |
ИнформацияОбОшибке() | Объект с деталями и причиной | Диагностика, логирование, проброс |
КраткоеПредставлениеОшибки() | Короткий текст для пользователя | Сообщения в интерфейсе |
ПодробноеПредставлениеОшибки() | Полный текст с местом возникновения | Журнал регистрации, отчёты об ошибках |
Связка «ИнформацияОбОшибке + ПодробноеПредставлениеОшибки» даёт в журнале регистрации номер строки и модуль, где возникла ошибка. Это экономит часы поиска по сравнению с разбором одной строки ОписаниеОшибки, особенно в фоновых заданиях без пользовательского интерфейса.
Проброс исключения выше по стеку
Не каждую ошибку нужно обрабатывать на месте. Часто нижний уровень кода не располагает контекстом для правильной реакции: процедура записи элемента справочника не знает, вызвана ли она из интерактивной формы или из пакетной загрузки, где ошибку надо собрать в общий отчёт. В таких случаях исключение пробрасывают выше.
Повторный вызов текущей ошибки
Простейший проброс — оператор ВызватьИсключение без параметров внутри блока Исключение. Он передаёт выше исходную ошибку со всеми деталями. Такой приём уместен, когда нужно выполнить частичную обработку (например, откатить локальные действия или записать в лог), но решение о реакции оставить вызывающему коду.
Обёртывание с добавлением контекста
Альтернатива — вызвать новое исключение с уточняющим текстом. Минус подхода в том, что теряются технические детали исходной ошибки, если их не включить в текст вручную. Поэтому при обёртывании добавляйте в новое сообщение краткое представление исходной ошибки.
Попытка
ЗаписатьОбъектВБазу(Объект);
Исключение
ИнфоОшибки = ИнформацияОбОшибке();
ВызватьИсключение СтрШаблон(
"Не удалось сохранить элемент ""%1"": %2",
Объект.Наименование,
КраткоеПредставлениеОшибки(ИнфоОшибки));
КонецПопытки;
Как выбрать действие
Исключения и транзакции
Самая критичная область применения исключений — работа с транзакциями. Если внутри транзакции возникло исключение и управление вышло за пределы блока без вызова ОтменитьТранзакцию(), платформа аварийно завершит выполнение с ошибкой. Поэтому канонический шаблон работы с транзакцией выглядит так:
НачатьТранзакцию();
Попытка
// изменение данных
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ИнфоОшибки = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Загрузка данных",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнфоОшибки));
ВызватьИсключение КраткоеПредставлениеОшибки(ИнфоОшибки);
КонецПопытки;
Обратите внимание на порядок: сначала отмена транзакции, затем логирование и проброс. Обратная последовательность опасна — если при записи в журнал или формировании текста возникнет новая ошибка, транзакция останется незакрытой.
Исключение или сообщение пользователю: что выбрать
Частая ошибка разработчиков — использовать ВызватьИсключение там, где достаточно сообщения пользователю с отказом от действия. Это разные сценарии. Сообщение с установкой параметра Отказ = Истина применяется для ожидаемых, штатных ситуаций: незаполненный реквизит, нарушение бизнес-правила, отрицательный остаток. Пользователь видит понятное сообщение, привязанное к полю формы, исправляет данные и повторяет действие.
Исключение оправдано для нештатных ситуаций, которые пользователь исправить не может: сбой соединения с внешним сервисом, нарушение целостности данных, ошибка программной логики. Исключение сигнализирует: «что-то сломалось, требуется вмешательство разработчика или администратора».
// Штатная проверка — сообщение, а не исключение
Если Не ЗначениеЗаполнено(Объект.Склад) Тогда
ТекстСообщения = "Поле ""Склад"" не заполнено";
ОбщегоНазначения.СообщитьПользователю(ТекстСообщения, , "Склад", "Объект", Отказ);
КонецЕсли;
Сравнение вариантов
Для ожидаемых ошибок ввода. Пользователь видит привязку к полю и может исправить данные. Не прерывает весь сеанс работы.
Для нештатных ситуаций и ошибок логики. Прерывает выполнение, требует обработчика выше по стеку.
Для передачи уже перехваченной ошибки выше после частичной обработки. Сохраняет все детали исходной ошибки.
Типичные ошибки при работе с исключениями
Даже опытные разработчики регулярно допускают одни и те же промахи. Самый вредный — пустой блок Исключение, маскирующий сбои. На втором месте — потеря деталей ошибки при пробросе: вместо подробного представления в текст попадает только общая фраза, и диагностика в рабочей базе становится невозможной.
Третья группа ошибок связана с клиент-серверной архитектурой. Исключение, возникшее на сервере и не перехваченное там, будет передано на клиент в виде общего текста — часть технических деталей теряется. Поэтому серверный код фоновых операций должен сам логировать подробности в журнал регистрации до того, как ошибка уйдёт на клиент.
Как проверить результат
Содержит причину, контекст и рекомендацию по исправлению
Общая фраза вида «Ошибка выполнения операции» без деталей
Есть запись уровня «Ошибка» с подробным представлением и местом возникновения
Записей нет или текст не позволяет найти строку кода
Данные полностью откачены, повторный запуск не находит «половинчатых» изменений
Часть данных изменилась, часть нет
Вызывающий код получает исходную ошибку с деталями
Верхний уровень получает пустое или усечённое описание
FAQ
Чем ВызватьИсключение отличается от метода Сообщить?
Сообщить просто выводит текст и не прерывает выполнение кода — программа продолжает работать дальше. ВызватьИсключение немедленно останавливает выполнение и передаёт управление ближайшему обработчику Попытка–Исключение, а при его отсутствии завершает всю цепочку вызовов. Для остановки операции с отказом в формах используют сообщение пользователю с параметром Отказ, а не Сообщить.
Можно ли вызвать исключение без текста?
Да, но только внутри блока Исключение — такой вызов повторно генерирует текущую перехваченную ошибку и пробрасывает её выше по стеку. Вызов без параметров в обычном коде приведёт к системной ошибке, поэтому вне обработчика всегда передавайте строку с описанием причины.
Как узнать, в какой строке кода возникла ошибка?
Используйте ИнформацияОбОшибке() внутри блока Исключение: объект содержит имя модуля и номер строки. Функция ПодробноеПредставлениеОшибки() формирует текст с этими данными — его удобно записывать в журнал регистрации через ЗаписьЖурналаРегистрации и затем находить по отбору.
Что произойдёт, если не перехватить исключение?
Выполнение текущей процедуры и всей цепочки вызовов прекратится. В интерактивном сеансе пользователь увидит окно с текстом ошибки, в фоновом задании задание завершится с ошибкой, а сведения попадут в журнал регистрации. Если исключение возникло внутри незакрытой транзакции, транзакция будет отменена платформой принудительно.
Работает ли ВызватьИсключение на клиенте и на сервере одинаково?
Синтаксис одинаков, но поведение различается. Неперехваченное серверное исключение передаётся на клиент в усечённом виде — часть технических деталей теряется. Поэтому серверный код должен сам записывать подробное представление ошибки в журнал регистрации до того, как исключение уйдёт на клиентскую сторону.
Как отличить системное исключение от вызванного вручную?
По тексту и структуре объекта ИнформацияОбОшибке: системные ошибки содержат типовые формулировки платформы (например, о нарушении уникальности индекса или отсутствии поля), а прикладные — текст, заданный разработчиком. Единого признака «источник ошибки» в объекте нет, поэтому полезно включать в собственные исключения узнаваемый контекст: имя операции, объекта или этапа обработки.
Что важно запомнить
Исключение вызывается оператором ВызватьИсключение с понятным текстом причины. Перехват делается через Попытка–Исключение, детали ошибки получают через ИнформацияОбОшибке и ПодробноеПредставлениеОшибки. Внутри транзакции обязательна отмена перед логированием и пробросом, а для ошибок ввода данных вместо исключения используйте сообщение пользователю с отказом.