Собралось без ошибок и упало у первого пользователя: четыре падения, которые не ловит проверка модулей

01.09.26

Разработка - Рефакторинг и качество кода

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

Обработка собралась. Синтаксический контроль прошёл. Валидатор формы прошёл. Автопрогон отработал и написал "ошибок нет". Отдаём.

Через час прилетает четыре падения подряд. Все четыре на том, что мы сами не нажимали.

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

 

Четыре падения

 

Что упало Сообщение Почему проверки молчали
НачатьЗапускПриложения с Неопределено без текста клиентская ветка вызывается только после сборки файла
чтение КонсольГотова Преобразование значения к типу Булево не может быть выполнено модульная переменная читалась раньше первого присваивания
Параметры = Новый Структура(...) Поле объекта недоступно для записи (Параметры) имя занято свойством управляемой формы, оно только для чтения
Элементы.ПолеТаблицы Поле объекта не обнаружено (ПолеТаблицы) элемент был в Form.xml, но загрузчик выбросил его молча

 

Общее у всех четырёх: синтаксис корректен. Поэтому и молчали проверки. Синтаксический контроль смотрит на текст модуля, а падает выполнение.

 

Случай первый и второй: состояние, которого ещё нет

Два первых падения это один класс, хоть и выглядят по-разному.

Модульная переменная объявлена, но присваивается в обработчике, который к моменту чтения ещё не отработал:

&НаКлиенте
Перем КонсольГотова;

&НаКлиенте
Процедура ОбновитьСостояние()
    Если КонсольГотова Тогда   // здесь Неопределено, а не Ложь
        ...

В 1С необъявленное состояние это Неопределено, а не Ложь. Условие с ним не сравнивает, а падает. Синтаксически всё безупречно: переменная объявлена, тип не указан, потому что его и нельзя указать.

Лечится одной строкой в ПриОткрытии или проверкой через ЗначениеЗаполнено. Но найти это можно только выполнением, причём выполнением именно в том порядке, в котором нажимает пользователь.

То же со вторым: НачатьЗапускПриложения получил Неопределено вместо пути, потому что путь заполняется в другой ветке, которая при этом сценарии не отрабатывала.

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

 

Случай третий: имя, которое уже занято платформой

Это ловушка, на которую наступают все, кто пишет формы руками:

&НаСервере
Процедура ЗаполнитьНастройки()
    Параметры = Новый Структура("Путь, Режим");   // Поле объекта недоступно для записи

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

Полный список того, во что нельзя писать, платформа нигде не печатает одним местом, но практически это Параметры, Элементы, Команды, Модифицированность, ЭтотОбъект и ещё несколько. Ошибка вылезает только при выполнении конкретной процедуры.

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

 

Случай четвёртый: одна буква, и элемента в форме нет

Вот это стоит запомнить всем, кто собирает формы из XML, генерирует их скриптами или правит выгрузку руками.

В Form.xml был элемент с тегом:

<SpreadsheetDocumentField name="ПолеТаблицы">

Правильно пишется SpreadSheetDocumentField, с заглавной S в середине. Разница в одной букве.

Что делает загрузчик конфигурации: выбрасывает такой элемент молча. Не ошибка, не предупреждение, не строка в лог. Сборка проходит успешно, файл получается, форма открывается. Элемента в ней просто нет, и первое же обращение Элементы.ПолеТаблицы падает с "Поле объекта не обнаружено".

При этом человек смотрит на Form.xml, видит там свой элемент и делает единственно возможный вывод: сломан модуль. Полчаса уходит на отладку кода, в котором всё правильно.

Это не единичная особенность одного тега. Ровно так же у нас пропадал VerticalStretch, написанный с другим регистром. Механика общая: неизвестный тег в форме не является ошибкой загрузки, он просто игнорируется.

Как проверять: после сборки сверять состав Form.xml с тем, что фактически оказалось в форме, и отдельно проверять теги по белому списку платформы. У нас это второй скрипт, и он ловит оба симптома: и пропавший элемент, и тег, которого не существует.

Дешёвый вариант без скриптов: собрать, открыть форму в конфигураторе и посмотреть глазами, все ли элементы на месте. Работает, пока элементов десяток.

Как воспроизвести это за пять минут

Если не верите, что платформа молчит, проверьте на любой тестовой обработке:

  1. Выгрузите обработку в XML.
  2. Найдите в Form.xml любой элемент и поменяйте регистр одной буквы в имени тега: например, CheckBoxField на CheckboxField.
  3. Загрузите обратно и соберите.
  4. Откройте форму.

Сборка пройдёт без единого сообщения. Элемента в форме не будет. В Form.xml, который лежит у вас на диске, он при этом на месте, и глазами вы его видите.

Отсюда практический признак для диагностики: если модуль падает на "Поле объекта не обнаружено", а элемент в XML есть, смотрите не на модуль, а на написание тега. Причём именно на регистр: платформа различает SpreadSheetDocumentField и SpreadsheetDocumentField как разные теги, из которых второй ей неизвестен.

Отличить "элемент выброшен" от "элемент не создан" помогает простая проверка прямо из модуля:

&НаСервере
Процедура ПроверитьСоставФормы()
    Для Каждого Элемент Из Элементы Цикл
        Сообщить(Элемент.Имя + " / " + ТипЗнч(Элемент));
    КонецЦикла;
КонецПроцедуры

Список того, что реально загрузилось, сверяется с тем, что вы писали в XML. Расхождение и есть ответ.

Что должен жать автопрогон

После этой истории у нас прогон устроен так, и это минимум, который окупается:

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

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

 

Почему все проверки были зелёными

Стоит разобрать отдельно, потому что это общий случай, а не частность про формы.

У нас было три уровня проверки, и каждый честно делал свою работу:

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

Каждый уровень отвечал "у меня чисто", и вместе они складывались в ощущение покрытия, которого не было. Это и есть самое дорогое в истории: не четыре падения, а ложная уверенность перед выдачей.

Сравните с тем, как выглядит правда: покрытие было одна команда из трёх, то есть 33 %, а отчёт печатал "ошибок нет" и выглядел как 100 %.

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

Тот же принцип работает и в обратную сторону. Когда среда падает без внятного текста, первым делом стоит прогнать через неё заведомо исправный артефакт: чужую рабочую обработку, простейший запрос, пустую форму. Одна минута, а разделяет "сломан мой код" и "сломана среда". У меня был случай, когда HTTP-сервис отдавал страницу 500 вместо JSON на любой вызов, и полчаса это выглядело как дефект модуля, пока тот же вызов не упал точно так же на заведомо рабочем файле. Дело оказалось в правах пользователя сервиса, а не в коде.

 

Что мы поменяли

Три вещи, все дешёвые:

  1. Автопрогон жмёт каждую команду каждой формы, включая те, что открывают другие формы, и пишет результат после каждой, а не общий итог в конце. Общий итог скрывал, что до третьей кнопки прогон не доходил.
  2. Проверка присваиваний в свойства формы по закрытому списку имён.
  3. Сверка Form.xml с фактическим составом формы плюс проверка тегов по белому списку.

Оба скрипта проверены воспроизведением: специально ломали регистр буквы в теге и специально писали в Параметры, оба симптома ловятся.

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

 

Правило, которое я вынес

Кнопка, которую не нажал автопрогон, это кнопка, которую нажмёт пользователь.

Формулировка звучит очевидно, пока не посмотришь на свой прогон и не посчитаешь, сколько команд он реально трогает. У нас было три команды и одна нажималась.

Второе следствие шире: отсутствие ошибки не равно успеху. Загрузчик, который молча выбрасывает неизвестный тег, сообщает об успехе. Прогон, который дошёл до первой кнопки, сообщает об успехе. Признаком успеха стоит считать полезный результат (элемент есть в форме, команда отработала и вернула данные), а не молчание инструмента.

 

Вопрос

Мне интересно, как с этим у тех, кто собирает формы генераторами. Судя по тому, что теги выбрасываются без предупреждения, наступать на это должны регулярно, но в обсуждениях я такого почти не встречал: обычно пишут про ошибки загрузки, а не про молчаливое исчезновение.

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

Вступайте в нашу телеграмм-группу Инфостарт

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Инструментарий разработчика Рефакторинг и качество кода Программист 1С 8.3 1С 8.5 Абонемент ($m)

Внешняя обработка для 1С, которая ищет в коде нарушения стандартов БСП и платформы (модальные вызовы, запросы в цикле, незакрытый привилегированный режим и др.) и часть из них чинит автоматически. Работает по фрагменту кода и по всей выгрузке конфигурации, с фоновым режимом через БСП и отчётом по найденному.

3 стартмани

27.08.2026    273    0    KonMa    0    

2

Перенос данных 1C Рефакторинг и качество кода Программист 1С 8.3 Бесплатно (free)

Правила обмена умеют лежать в двух местах сразу: в макете конфигурации, где их находит глобальный поиск и где их так удобно поправить, и в регистре сведений, откуда они на самом деле исполняются. Пока не проверишь, какой источник включён у плана обмена, правка макета выглядит сделанной и не делает ничего. Разбор задачи, где одно и то же значение ставки оказалось зашито в четырёх местах трёх разных слоёв: карта соответствий в модуле веб-сервиса, обработчик "ПослеЗагрузки" в правиле обмена, числовой ВЫБОР с внутренним ИНАЧЕ 0 внутри сгенерированных правил и общий модуль интеграции с внешним поставщиком чеков. Отдельно - почему у истории с вернувшимися карточками нет доказанной причины, хотя признак сузили до одного вида номенклатуры, и как тестовый прогон на пяти записях сломал сходимость итогового отчёта.

27.08.2026    487    nedomolkov.ivan    0    

1

HighLoad оптимизация Рефакторинг и качество кода Системный администратор Программист 1С 8.3 Бесплатно (free)

Режим снимка(snapshot) убрал почти все дедлоки: с 73 в час до 7-8. Через несколько дней выяснилось, что разделяемые замки раньше сами обеспечивали сериализацию там, где код читал, решал и писал. После включения снимка эта защита пропала. Пришлось пересмотреть код: 234 места с намерением записи, 59 оставили разделяемыми, чтобы не получить взаимные блокировки. Проверка "хватит ли данных" часто стояла выше открытия транзакции - такие места линтер и ревьюер не видят. Дальше - про поддельные блокировки, опасность смены умолчания и шесть проверок.

25.08.2026    632    nedomolkov.ivan    1    

4

Инструментарий разработчика Рефакторинг и качество кода Программист 1С 8.3 Абонемент ($m)

Обработка читает исходники других внешних обработок и отчётов прямо из базы и отвечает на два вопроса: с какой из них начинать смотреть и что именно в ней смотреть. На выходе HTML-отчёт: индекс качества от 0 до 100, светофор, оценка технического долга в минутах и находки с номером строки, фрагментом кода и подсветкой синтаксиса. Двадцать восемь правил: запрос в цикле, транзакция без отката, небезопасное выполнение строки, тяжёлые схемы компоновки. Считается всё на чистом BSL, без интернета, внешних компонент и отдельного сервиса рядом, поэтому анализируемый код не покидает машину. Прогон по двум десяткам обработок выстраивает их по индексу качества, худшие сверху, и сразу видно, с чего начинать разбор.

10 стартмани

20.08.2026    577    2    nedomolkov.ivan    2    

4

Рефакторинг и качество кода Программист 1С 8.3 Бесплатно (free)

Библиотека из 6 слоев анализа, от внешней обработки до готового отчёта. Каталог из двадцати восьми правил, у каждого свой уровень и вес. И всё это крутится на чистом BSL, без Java, без git, без какого-то внешнего сервера анализа и без отправки чужого кода наружу. Разбираю, как устроен этот анализатор внешних обработок и по каким признакам он решает, что код плохой. Почему запрос в цикле получает шестьдесят баллов, как правило вообще проходит фильтр перед релизом и почему часть правил у меня помечена как сломанные. Проверял я его на себе: взял семнадцать своих обработок, которые лежат на площадке и продаются. Получил 239 замечаний и пятнадцать рабочих дней технического долга. У самой худшей индекс качества - 20 из 100 и красный светофор. А ещё расскажу, где у инструмента границы, за которые он не заходит, и про грабли - самая дорогая из них молчала.

20.08.2026    910    nedomolkov.ivan    0    

1

Рефакторинг и качество кода Программист 1С 8.3 Бесплатно (free)

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

20.08.2026    889    n_mezentsev    10    

2

Рефакторинг и качество кода Нейросети Программист Бесплатно (free)

Передача двух модулей BSL в Cursor AI для классического сравнения без использования искусственного интеллекта (ИИ) и для проведения code review с помощью ИИ.

12.08.2026    2812    ScaNNer    0    

5

Рефакторинг и качество кода Обновление 1С Программист 1С 8.3 1С:ERP. Управление холдингом Бесплатно (free)

К нам на проект сложного обновления пришла конфигурация «1С:ERP УХ» с доработанным отчетом, построенным на базе типового «Задолженность поставщикам по срокам». После обновления целевая форма открывалась без учета переданных данных.

05.08.2026    1025    1c-izh    4    

4
Для отправки сообщения требуется регистрация/авторизация