К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как вызвать исключение в 1С: практическое руководство

Как вызвать исключение в 1С: оператор ВызватьИсключение, конструкция Попытка–Исключение, проброс ошибок, логирование в журнал регистрации и типичные ошибки.

Исключение в 1С — это механизм принудительной остановки выполнения кода при возникновении ошибочной ситуации. Разработчик может как перехватывать системные исключения через конструкцию «Попытка — Исключение», так и самостоятельно генерировать их оператором ВызватьИсключение, когда логика прикладного решения требует прервать операцию: например, при незаполненном обязательном реквизите, ошибке обмена данными или недопустимом состоянии объекта.

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

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

Синтаксис оператора ВызватьИсключение

Базовая форма оператора предельно проста: после ключевого слова указывается строка с описанием причины. Как только интерпретатор встречает этот оператор, выполнение текущего кода немедленно прекращается.

Если Не ЗначениеЗаполнено(ДоговорКонтрагента) Тогда

ВызватьИсключение "Не указан договор контрагента. Проведение документа невозможно.";

КонецЕсли;

Текст исключения должен отвечать на два вопроса: что пошло не так и что сделать, чтобы исправить ситуацию. Сообщение вида «Ошибка!» не даёт ни диагностики, ни пути решения и вынуждает разбираться в коде. Хороший текст содержит контекст: имя объекта, значение проблемного параметра, ожидаемое условие.

Оператор можно вызывать без параметров, но только внутри блока Исключение — такой вызов означает повторный проброс текущей ошибки выше по стеку. Вне обработчика вызов без параметра приведёт к системной ошибке.

Перехват исключений: Попытка — Исключение — КонецПопытки

Чтобы ошибка не оборвала выполнение всей операции, потенциально опасный код помещают в блок Попытка. Если внутри него возникает исключение — системное или вызванное вручную — управление переходит в блок Исключение, где ошибку можно проанализировать и обработать.

Попытка

Результат = ВыполнитьОбменДанными(Узел);

Исключение

ИнфоОшибки = ИнформацияОбОшибке();

ЗаписьЖурналаРегистрации("Обмен данными",

УровеньЖурналаРегистрации.Ошибка, , ,

ПодробноеПредставлениеОшибки(ИнфоОшибки));

Сообщить("Обмен не выполнен: " + КраткоеПредставлениеОшибки(ИнфоОшибки));

КонецПопытки;

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

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

Получение информации об ошибке

Внутри блока Исключение доступны два подхода к получению сведений об ошибке. Классический метод — функция ОписаниеОшибки(), которая возвращает строку с описанием. Современный и более информативный способ — функция ИнформацияОбОшибке(), возвращающая объект со структурированными данными.

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

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

Проброс исключения выше по стеку

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

Повторный вызов текущей ошибки

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

Обёртывание с добавлением контекста

Альтернатива — вызвать новое исключение с уточняющим текстом. Минус подхода в том, что теряются технические детали исходной ошибки, если их не включить в текст вручную. Поэтому при обёртывании добавляйте в новое сообщение краткое представление исходной ошибки.

Попытка

ЗаписатьОбъектВБазу(Объект);

Исключение

ИнфоОшибки = ИнформацияОбОшибке();

ВызватьИсключение СтрШаблон(

"Не удалось сохранить элемент ""%1"": %2",

Объект.Наименование,

КраткоеПредставлениеОшибки(ИнфоОшибки));

КонецПопытки;

Маршрут решения

Как выбрать действие

Ошибку можно исправить или обойти на местеОбработайте её в блоке Исключение и продолжите выполнение
Нужно залогировать ошибку, но решение принимает вызывающий кодЗапишите в журнал регистрации и выполните ВызватьИсключение без параметров
Верхнему уровню не хватает контекста для понимания ошибкиОбёрните исключение новым текстом, включив в него краткое представление исходной ошибки
Ошибка пользовательская (незаполненный реквизит)Используйте сообщение пользователю с отказом, а не исключение

Исключения и транзакции

Самая критичная область применения исключений — работа с транзакциями. Если внутри транзакции возникло исключение и управление вышло за пределы блока без вызова ОтменитьТранзакцию(), платформа аварийно завершит выполнение с ошибкой. Поэтому канонический шаблон работы с транзакцией выглядит так:

НачатьТранзакцию();

Попытка

// изменение данных

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ИнфоОшибки = ИнформацияОбОшибке();

ЗаписьЖурналаРегистрации("Загрузка данных",

УровеньЖурналаРегистрации.Ошибка, , ,

ПодробноеПредставлениеОшибки(ИнфоОшибки));

ВызватьИсключение КраткоеПредставлениеОшибки(ИнфоОшибки);

КонецПопытки;

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

Исключение или сообщение пользователю: что выбрать

Частая ошибка разработчиков — использовать ВызватьИсключение там, где достаточно сообщения пользователю с отказом от действия. Это разные сценарии. Сообщение с установкой параметра Отказ = Истина применяется для ожидаемых, штатных ситуаций: незаполненный реквизит, нарушение бизнес-правила, отрицательный остаток. Пользователь видит понятное сообщение, привязанное к полю формы, исправляет данные и повторяет действие.

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

// Штатная проверка — сообщение, а не исключение

Если Не ЗначениеЗаполнено(Объект.Склад) Тогда

ТекстСообщения = "Поле ""Склад"" не заполнено";

ОбщегоНазначения.СообщитьПользователю(ТекстСообщения, , "Склад", "Объект", Отказ);

КонецЕсли;

Сравнение вариантов

Сообщение пользователю + Отказ

Для ожидаемых ошибок ввода. Пользователь видит привязку к полю и может исправить данные. Не прерывает весь сеанс работы.

ВызватьИсключение с текстом

Для нештатных ситуаций и ошибок логики. Прерывает выполнение, требует обработчика выше по стеку.

Проброс без параметров

Для передачи уже перехваченной ошибки выше после частичной обработки. Сохраняет все детали исходной ошибки.

Типичные ошибки при работе с исключениями

Даже опытные разработчики регулярно допускают одни и те же промахи. Самый вредный — пустой блок Исключение, маскирующий сбои. На втором месте — потеря деталей ошибки при пробросе: вместо подробного представления в текст попадает только общая фраза, и диагностика в рабочей базе становится невозможной.

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

Типичные ошибки
01
Пустой блок Исключение — ошибка проглатывается, данные остаются в неопределённом состоянии, поиск причины сбоя невозможен
02
Проброс нового исключения без текста исходной ошибки — теряются детали, в журнале видно только обобщённую фразу
03
ВызватьИсключение без параметров вне блока Исключение — системная ошибка вместо прикладного сообщения
04
Исключение вместо сообщения пользователю при ошибках ввода — пользователь видит технический текст и не понимает, что исправить
05
ОтменитьТранзакцию после логирования — при ошибке записи в журнал транзакция остаётся незакрытой
Контрольные точки

Как проверить результат

Текст исключения
Норма

Содержит причину, контекст и рекомендацию по исправлению

Тревожный признак

Общая фраза вида «Ошибка выполнения операции» без деталей

Журнал регистрации после сбоя
Норма

Есть запись уровня «Ошибка» с подробным представлением и местом возникновения

Тревожный признак

Записей нет или текст не позволяет найти строку кода

Поведение транзакции при ошибке
Норма

Данные полностью откачены, повторный запуск не находит «половинчатых» изменений

Тревожный признак

Часть данных изменилась, часть нет

Повторный проброс
Норма

Вызывающий код получает исходную ошибку с деталями

Тревожный признак

Верхний уровень получает пустое или усечённое описание

FAQ

Чем ВызватьИсключение отличается от метода Сообщить?

Сообщить просто выводит текст и не прерывает выполнение кода — программа продолжает работать дальше. ВызватьИсключение немедленно останавливает выполнение и передаёт управление ближайшему обработчику Попытка–Исключение, а при его отсутствии завершает всю цепочку вызовов. Для остановки операции с отказом в формах используют сообщение пользователю с параметром Отказ, а не Сообщить.

Можно ли вызвать исключение без текста?

Да, но только внутри блока Исключение — такой вызов повторно генерирует текущую перехваченную ошибку и пробрасывает её выше по стеку. Вызов без параметров в обычном коде приведёт к системной ошибке, поэтому вне обработчика всегда передавайте строку с описанием причины.

Как узнать, в какой строке кода возникла ошибка?

Используйте ИнформацияОбОшибке() внутри блока Исключение: объект содержит имя модуля и номер строки. Функция ПодробноеПредставлениеОшибки() формирует текст с этими данными — его удобно записывать в журнал регистрации через ЗаписьЖурналаРегистрации и затем находить по отбору.

Что произойдёт, если не перехватить исключение?

Выполнение текущей процедуры и всей цепочки вызовов прекратится. В интерактивном сеансе пользователь увидит окно с текстом ошибки, в фоновом задании задание завершится с ошибкой, а сведения попадут в журнал регистрации. Если исключение возникло внутри незакрытой транзакции, транзакция будет отменена платформой принудительно.

Работает ли ВызватьИсключение на клиенте и на сервере одинаково?

Синтаксис одинаков, но поведение различается. Неперехваченное серверное исключение передаётся на клиент в усечённом виде — часть технических деталей теряется. Поэтому серверный код должен сам записывать подробное представление ошибки в журнал регистрации до того, как исключение уйдёт на клиентскую сторону.

Как отличить системное исключение от вызванного вручную?

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

Итог

Что важно запомнить

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