Почему ломается молча Правило ноль: не собирать дамп с нуля PropertyState при пустом ChildObjects Директива против callType Загрузка не равна компиляции SafeMode при обновлении Перенос с 8.5 на 8.3 Мелочи по часу каждая Промт целиком Частые вопросы

Расширение конфигурации 1С умеет ломаться самым неприятным способом из возможных: без ошибки.

Файл загрузился. Конфигуратор промолчал. Обновление конфигурации базы данных прошло. Роль расширения в сеансе активна, синоним у документа новый — значит, применилось. А обработчик &Перед не выполняется. Не падает, не пишет в лог — просто не вызывается. Платформа идёт типовым путём, как будто расширения в базе нет.

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

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

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

Почему расширения ломаются молча

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

  1. XML-структура дампа. Проверяется при загрузке из файлов. Здесь ошибка честная: Конфигуратор скажет. Или, в худшем случае, зависнет.
  2. Привязка к базовой конфигурации. Заимствованные объекты, маркеры расширенных свойств, директивы обработчиков. Ошибки этого слоя не диагностируются вообще: расширение загружено, а код не привязан к тому, что должен перехватывать.
  3. Компиляция модулей. Происходит при первой инициализации модуля в рантайме. Не скомпилировалось — расширение молча не применяется целиком.

Второй и третий слой и дают эффект «загрузилось, но не работает». Отсюда правило, которое стоит принять до всего остального:

Факт загрузки — не доказательство. Доказательство — вызванная экспортная функция модуля и проверенное поведение в живом клиенте.

Правило ноль: не собирайте дамп с нуля

Самая дорогая ошибка в начале — попросить ИИ «сделай структуру расширения по документации». Он сделает. Выглядеть будет правильно. Конфигуратор при загрузке повесится.

Правильный старт: в целевой базе выгрузить в файлы любое уже работающее расширение (Конфигуратор → Расширения → Выгрузить в файлы) и использовать его как эталон формата. Оттуда берётся всё, что нельзя угадать: атрибут version в шапке XML, режим совместимости, UUID языка, вид заимствованных объектов.

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

Заимствовали объект ради модуля — нужен PropertyState

Классическая ситуация: надо перехватить проведение документа. Реквизиты не добавляем, форму не трогаем — только модуль. <ChildObjects/> пустой.

Расширение загружается. Роль активна. Обработчик не работает.

Причина: при пустом ChildObjects модуль не считается расширенным свойством, и .bsl остаётся мёртвым файлом. В <Имя>.xml внутри <InternalInfo>, после блоков GeneratedType, нужен маркер:

<xr:PropertyState>
  <xr:Property>ObjectModule</xr:Property>
  <xr:State>Extended</xr:State>
</xr:PropertyState>

Для модуля менеджера — ManagerModule, для формы — Form.

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

Директива обработчика обязана совпадать с callType

В Forms/<Форма>/Ext/Form.xml событие объявлено так:

<Event name="OnCreateAtServer" callType="After">МояПроцедура</Event>

Значит, в модуле формы процедура помечается &После("ПриСозданииНаСервере"). Не &НаСервере. С неверной директивой обработчик не привязывается — молча, без ошибки.

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

Успешная загрузка не значит компилируемый модуль

Пакетная загрузка вернула код 0, обновление конфигурации базы данных прошло. Кажется, всё.

А в модуле — вызов метода, которого в этом контексте нет. Например, СообщитьПользователю недоступна в модуле объекта Расходной накладной в УНФ. Компилятор скажет «Процедура или функция с указанным именем не определена» → ошибка инициализации модуля → расширение не применяется целиком. Платформа спокойно идёт типовым путём и падает уже на своей ошибке учёта, в совершенно другом месте. Полдня ушло на то, чтобы связать одно с другим.

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

Отдельно: перехваты модуля объекта (проведение, запись) проверять только в живом клиенте. Через внешнее соединение они не применяются — тест покажет типовое поведение и соврёт.

SafeMode: нужен при создании, ломает при обновлении

<SafeMode>false</SafeMode> при первом создании расширения указывать надо — иначе по умолчанию безопасный режим включён, и код не сможет ни читать файлы, ни писать объекты.

А при обновлении уже существующего расширения этот же тег роняет загрузку: код возврата 0, в базе ничего не изменилось. Свойство наследуется, дублировать нельзя.

Вторая причина «код 0, а изменений нет» — открытый на хосте Конфигуратор. Он блокирует информационную базу для конфигурирования, и в логе это видно, а код возврата всё равно нулевой.

Перенос расширения между платформами

Расширение, собранное Конфигуратором 8.5.1, не грузится на 8.3.x: «Неизвестная версия формата 2.21 загружаемого файла». Понижаете version во всех xml — и упираетесь во второй барьер: лексемы перечислений, которых в 8.3 не было. Например <WindowOpeningMode>DontBlock</WindowOpeningMode>. Такие необязательные теги вырезаются целиком — свойство наследуется от исходной формы.

Отдельная тонкость: в Ext/Form.xml захваченной формы версия указана дважды — в основной копии и внутри <BaseForm>. Правите одну, вторая ломает загрузку.

Если таких мест много, дешевле снять дамп заимствуемых объектов на целевой базе её же Конфигуратором и пересобрать заимствование там — получите родные формат, лексемы и UUID.

Мелочи, каждая из которых стоит часа

Промт: собрать расширение без этих ошибок

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

Внутри:

Работает с любым ассистентом, который умеет писать файлы: Claude Code, Cursor, Copilot.

Скачать промт бесплатно

Файл лежит в моём телеграм-канале, там же выкладываю новые версии и другие инструменты для 1С. Промт живой — дополняю по мере новых грабель.

Забрать промт →

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

Почему расширение 1С загрузилось, но не работает?

Три частых причины: не поставлен PropertyState при пустом ChildObjects; директива обработчика не совпадает с callType; модуль не компилируется из-за недоступного в этом контексте метода. В последнем случае расширение молча не применяется целиком.

Как быстро проверить, применилось ли расширение?

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

Можно ли собрать расширение без Конфигуратора?

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

Почему обработчик работает у меня и не работает у клиента?

Чаще всего дело в платформе и релизе конфигурации. UUID заимствуемых объектов привязаны к релизу базы-источника, а формат XML — к версии платформы. Расширение, собранное на 8.5, на 8.3 не загрузится вообще, а собранное на другом релизе типовой может загрузиться и не привязаться.

Ещё по теме 1С и ИИ

Сделал HTTP-сервер прямо внутри 1С — как устроен OneBridge, бесплатный MCP-сервер, через который ассистент читает метаданные и данные базы напрямую.

Написал обработку для 1С за 55 минут — реальный кейс: загрузка отчёта Wildberries в УНФ, без единой строки, написанной руками.

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