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