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

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

Как работает Попытка в 1С: обработка исключений на практике

Как работает Попытка в 1С: синтаксис Попытка-Исключение-КонецПопытки, обработка ошибок, ОписаниеОшибки, типовые сценарии и частые ошибки разработчиков.

Конструкция Попытка...Исключение...КонецПопытки — встроенный механизм языка 1С, который позволяет перехватывать ошибки времени выполнения и не давать коду завершиться аварийно. Без неё любая непредвиденная ситуация — деление на ноль, обращение к несуществующему реквизиту, ошибка при чтении файла — прерывает выполнение процедуры и показывает пользователю системное сообщение об ошибке.

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

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

Синтаксис конструкции Попытка-Исключение

Полная форма конструкции выглядит так:

Попытка

// код, который может вызвать ошибку

Результат = Значение1 / Значение2;

Исключение

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

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

ИнфоОшибки.Описание);

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

Есть и сокращённая форма без блока обработки — она просто подавляет ошибку:

Попытка

ВыполнитьОперацию();

Исключение

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

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

Как получить информацию об ошибке

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

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

Исключение

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

Сообщить("Ошибка: " + Инфо.Описание + " | Модуль: "

+ Инфо.ИмяМодуля + " | Строка: " + Инфо.НомерСтроки);

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

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

bsl
Исключение
    Инфо = ИнформацияОбОшибке();
    ЗаписьЖурналаРегистрации("Обмен", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(Инфо));
КонецПопытки;

Типовые сценарии применения

Чаще всего Попытка используется при работе с внешними ресурсами: файлами, веб-сервисами, HTTP-запросами, COM-объектами. Эти операции могут завершиться ошибкой по причинам, не зависящим от кода, — сеть недоступна, файл занят другим процессом, сервер вернул ошибку.

Работа с файлами и внешними соединениями

Попытка

ТекстДок = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);

Содержимое = ТекстДок.Прочитать();

ТекстДок.Закрыть();

Исключение

Сообщить("Не удалось прочитать файл: " + ОписаниеОшибки());

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

Транзакции с откатом

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

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

Попытка

ДокументОбъект.Записать();

РегистрНабор.Записать();

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

Исключение

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

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

ОписаниеОшибки());

ВызватьИсключение; // пробрасываем ошибку выше

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

Повтор операции при временном сбое

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

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

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

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

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

КонецЕсли;

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

Частые ошибки при работе с Попытка

  • Пустой блок Исключение. Самая распространённая ошибка: ошибка подавляется, никто о ней не узнаёт, а данные оказываются незаписанными или частично записанными.
  • Слишком широкий блок Попытка. Если в Попытку помещено 200 строк кода, понять, какая именно строка упала, сложно. Обертывайте только те операции, где ошибка действительно возможна и ожидаема.
  • Забытый ОтменитьТранзакцию(). Если транзакция начата до Попытки, а в Исключении её не откатили, соединение остаётся с открытой транзакцией.
  • Использование Попытки вместо проверки условий. Если можно проверить делитель на ноль через Если — проверяйте. Попытка предназначена для непредсказуемых сбоев, а не для замены логики.
  • Потеря вложенной причины. При записи ошибки используют только ОписаниеОшибки() и теряют цепочку Причина, из-за чего корень проблемы не виден.
Типичные ошибки
01
Пустое Исключение скрывает сбой — пользователь думает, что операция выполнена, а данные потеряны
02
Попытка вокруг всего тела процедуры — невозможно локализовать строку сбоя
03
Нет ОтменитьТранзакции в Исключении — транзакция зависает и держит блокировки
04
Ошибка записывается только пользователю в Сообщить, но не в журнал регистрации — при повторном обращении диагностировать нечего

Как проверить, что обработка работает правильно

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

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

Контрольные точки

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

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

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

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

Записей нет — ошибка проглочена молча

Сообщение пользователю
Норма

Понятный текст: что случилось и что делать

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

Системное окно с техническим стеком или тишина

Повторный запуск после устранения причины
Норма

Операция выполняется успешно

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

Ошибки о блокировках, занятых файлах, открытых транзакциях

Когда Попытка не нужна: альтернативы

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

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

Попытка или проверка условия

Проверка через Если

Подходит для предсказуемых ситуаций: пустые значения, делитель, тип данных. Код читаемее и быстрее.

Попытка-Исключение

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

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

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

Итог

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

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

Частые вопросы

Чем ОписаниеОшибки() отличается от ИнформацияОбОшибке()?

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

Можно ли использовать Попытку в клиентском коде управляемых форм?

Да, конструкция работает и на клиенте, и на сервере. Однако учитывайте контекст: серверные процедуры, вызванные с клиента, обрабатывают исключения сами, а необработанная серверная ошибка вернётся на клиент в виде общего сообщения.

Что произойдёт, если ошибка возникнет внутри блока Исключение?

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

Почему после ошибки в транзакции 1С ругается на блокировки у других пользователей?

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

Правда ли, что Попытка замедляет выполнение кода?

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

Как показать пользователю понятное сообщение вместо технического текста?

В блоке Исключение запишите технические детали через ЗаписьЖурналаРегистрации, а пользователю выведите через Сообщить или ПоказатьПредупреждение краткий текст: что не удалось сделать и какое действие предпринять. Не выводите пользователю стек вызовов и имена модулей.