Расширение конфигурации 1С умеет ломаться самым неприятным способом из возможных: без ошибки.
Файл загрузился. Конфигуратор промолчал. Обновление конфигурации базы данных прошло. Роль расширения в сеансе активна, синоним у документа новый — значит, применилось. А обработчик &Перед не выполняется. Не падает, не пишет в лог — просто не вызывается. Платформа идёт типовым путём, как будто расширения в базе нет.
За последние месяцы я собрал полтора десятка расширений — для УНФ, Бухгалтерии, Комплексной автоматизации, для мебельной фабрики и для клиентов на серверных базах. Почти всё писал с ИИ: ассистент читает метаданные, генерит XML и модули, я проверяю и загружаю. Скорость выросла в разы. Но каждое второе расширение сначала не работало, и почти всегда — вот этим молчаливым способом.
Ошибки повторялись. Я их выписывал. Получился список, который теперь отдаю ассистенту в начале работы — и расширения стали собираться с первого раза. Список ниже, промт целиком — в конце.
Коротко о себе: разворачиваю сервера, пишу обработки и расширения 1С, делаю телеграм-ботов и интеграции. Работаю один, поэтому автоматизирую всё, что автоматизируется, и ИИ у меня в проде каждый день, а не для развлечения.
Почему расширения ломаются молча
У обычного кода 1С есть компилятор, и он ругается сразу. У расширения три отдельных слоя проверки, и про ошибку каждого вы узнаёте в своё время:
- XML-структура дампа. Проверяется при загрузке из файлов. Здесь ошибка честная: Конфигуратор скажет. Или, в худшем случае, зависнет.
- Привязка к базовой конфигурации. Заимствованные объекты, маркеры расширенных свойств, директивы обработчиков. Ошибки этого слоя не диагностируются вообще: расширение загружено, а код не привязан к тому, что должен перехватывать.
- Компиляция модулей. Происходит при первой инициализации модуля в рантайме. Не скомпилировалось — расширение молча не применяется целиком.
Второй и третий слой и дают эффект «загрузилось, но не работает». Отсюда правило, которое стоит принять до всего остального:
Факт загрузки — не доказательство. Доказательство — вызванная экспортная функция модуля и проверенное поведение в живом клиенте.
Правило ноль: не собирайте дамп с нуля
Самая дорогая ошибка в начале — попросить ИИ «сделай структуру расширения по документации». Он сделает. Выглядеть будет правильно. Конфигуратор при загрузке повесится.
Правильный старт: в целевой базе выгрузить в файлы любое уже работающее расширение (Конфигуратор → Расширения → Выгрузить в файлы) и использовать его как эталон формата. Оттуда берётся всё, что нельзя угадать: атрибут 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.
Мелочи, каждая из которых стоит часа
- UUID только настоящие. Свежие uuid4 во всех атрибутах
uuidи вContainedObject → ObjectId. АClassIdне трогать — это идентификаторы типов объектов. Плейсхолдеры видаa1111111-…, которые любит подставлять ИИ, ломают загрузку. - BOM и CRLF. Файлы дампа — UTF-8 с BOM, переводы строк CRLF.
- Реквизит табчасти — не реквизит шапки. У
AttributeвнутриTabularSectionнетFillValueиFillFromFillingValue. Скопировали блок из шапки — удалите эти строки, иначе Конфигуратор ругнётся, что свойство не входит в состав объекта метаданных. - Роль минимальная, без
Ext/Rights.xml. - Версию расширения бампать при каждой правке.
<Version>— сегодняшняя дата. Иначе по базе не отличить, применился фикс или загрузилась прошлая сборка. - Заимствование — последнее средство. Если задача решается новым объектом (общая команда, общий модуль, обработка, общий макет), делайте так: новые объекты ссылаются на типы конфигурации по имени и не требуют реальных type-UUID, привязанных к релизу.
- Полную выгрузку конфигурации КА, ERP или УТ не гнать. Только точечный дамп нужных объектов. Полная выгрузка большой типовой съедает память рабочего процесса — у меня от этого падала соседняя база кластера.
- Свойства программно создаваемых элементов формы компилятор не проверяет. У
ТаблицаФормынет свойстваОтображатьЗаголовок— форма не откроется, и ошибка будет при открытии, а не при сборке. Проверять программный интерфейс надо открытием формы.
Промт: собрать расширение без этих ошибок
Всё это я собрал в один текстовый файл. Схема работы простая: вставляете его в начало диалога с ИИ, заполняете блок «Задача» — платформа, конфигурация, релиз, что нужно сделать — и дальше работаете обычными сообщениями.
Внутри:
- 16 правил с описанием симптомов — не «делай правильно», а «вот что сломается и как это выглядит»;
- порядок работы из 8 шагов: от выгрузки эталона до проверки в живом клиенте;
- чеклист самопроверки из 12 пунктов, который ассистент проходит перед выдачей результата;
- таблица «симптом → причина» — по ней ошибка находится за минуту вместо вечера.
Работает с любым ассистентом, который умеет писать файлы: 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С не говорит ни слова.