При обновлении типовых конфигураций (например, «Бухгалтерия для Казахстана», «Бухгалтерия предприятия» и других) разработчики часто сталкиваются со следующей проблемой: внешняя обработка или код интеграции, которые стабильно работали годами, внезапно начинают аварийно завершаться. Ошибка выглядит следующим образом: «Несоответствие типов (параметр номер '1') (Неверный тип параметра. Допустимы только примитивные типы, ссылки, структура)». Примечательно, что сбой происходит на самой обычной строке кода — при вызове метода Записать().
В этой статье мы подробно разберем, почему возникает данная ошибка, как изменение режима совместимости платформы (например, переход с версии 8.3.8 на 8.3.11 и выше) влияет на выполнение кода, и как по шагам локализовать и исправить эту проблему.
Для начала проанализируем поведение платформы «1С:Предприятие 8.3» при смене режима совместимости. Главный «виновник» ошибки — изменение строгости контроля типов при передаче параметров в общие модули, у которых установлено свойство «Повторное использование возвращаемых значений» (кэшируемые модули).
Согласно официальной документации и стандартам разработки фирмы «1С», на параметры функций в таких модулях накладываются жесткие ограничения. Параметрами могут выступать только:
Число, Строка, Дата, Булево, Неопределено, Null).СправочникСсылка.Контрагенты, ДокументСсылка.ПлатежноеПоручениеВходящее).В старых режимах совместимости (до 8.3.8 включительно) платформа выполняла проверку параметров поверхностно. Если в функцию кэшируемого модуля передавалась структура, внутри которой находился «запрещенный» объект (например, сам ДокументОбъект или ТаблицаЗначений), система могла проигнорировать это нарушение и выполнить код. Однако, начиная с режима совместимости 8.3.9 и окончательно в 8.3.11, платформа стала выполнять рекурсивный (глубокий) анализ содержимого передаваемых структур. Если во вложенных свойствах структуры обнаруживается недопустимый тип данных, выполнение мгновенно прерывается системным исключением.
Рассмотрим ситуацию, когда разработчик пытается записать документ программно, используя простейший код:
НовыйДокумент = Документы.ПлатежноеПоручениеВходящее.СоздатьДокумент();
// Заполнение реквизитов документа...
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
Казалось бы, в этом коде нет обращений к функциям с повторным использованием возвращаемых значений. Почему же ошибка возникает именно здесь? Дело в том, что метод Записать() инициирует сложную цепочку событий:
ПередЗаписью и ПриЗаписи в модуле самого объекта.Внутри одной из таких подписок на события (например, проверяющей права доступа, параметры регистрации для обмена данными или заполнение дополнительных реквизитов) вызывается функция кэшируемого общего модуля. В эту функцию в качестве параметра передается структура настроек, в которую по ошибке поместили сам объект документа (переменную со значением типа ДокументОбъект) вместо его ссылки (ДокументСсылка).
Поскольку ошибка происходит во время транзакции записи в недрах подписок на события, обычный пошаговый проход по коду внешней обработки (клавишей F10) не поможет быстро найти источник сбоя. Нам потребуется настроить отладчик на остановку в момент возникновения системного исключения.
Выполним следующие действия по шагам:
При нажатии кнопки записи платформа аварийно остановит выполнение кода ровно на той строке общего модуля, которая спровоцировала конфликт. Теперь мы можем открыть панель «Стек вызовов» и увидеть всю цепочку событий: от нашего метода Записать() до конкретной подписки на событие и сбойного вызова функции.
Допустим, отладчик остановил нас в процедуре подписки на событие перед записью документа. Проанализируем типичный ошибочный код, который часто встречается в устаревших или некорректно обновленных конфигурациях:
// ПРИМЕР НЕКОРРЕКТНОГО КОДА В ПОДПИСКЕ НА СОБЫТИЕ
Процедура ОпределитьПараметрыРегистрацииПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
ПараметрыОбмена = Новый Структура;
ПараметрыОбмена.Вставить("Документ", Источник); // Ошибка! Источник имеет тип ДокументОбъект
ПараметрыОбмена.Вставить("РежимЗаписи", РежимЗаписи);
// Вызов функции кэшируемого модуля БСП
Правила = ОбщегоНазначенияВызовСервераПовтИсп.ПолучитьПравилаРегистрацииОбъекта(ПараметрыОбмена);
КонецПроцедуры
В данном примере в структуру параметров ПараметрыОбмена передается переменная Источник, имеющая тип ДокументОбъект.ПлатежноеПоручениеВходящее. Поскольку функция ПолучитьПравилаРегистрацииОбъекта находится в модуле с повторным использованием возвращаемых значений, платформа 1С в режиме совместимости 8.3.11 видит в структуре сложный тип данных и возвращает ошибку несоответствия типов.
Для исправления этой ситуации нам необходимо передавать в структуру не сам объект, а ссылку на него. Перепишем этот код правильно:
// ПРИМЕР ИСПРАВЛЕННОГО И КОРРЕКТНОГО КОДА
Процедура ОпределитьПараметрыРегистрацииПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
ПараметрыОбмена = Новый Структура;
// Передаем ссылку вместо объекта
Если ЗначениеЗаполнено(Источник.Ссылка) Тогда
ПараметрыОбмена.Вставить("Документ", Источник.Ссылка);
Иначе
// Если документ новый и еще не записан, получаем для него новый идентификатор
ПараметрыОбмена.Вставить("Документ", Источник.ПолучитьСсылкуНового());
КонецЕсли;
ПараметрыОбмена.Вставить("РежимЗаписи", РежимЗаписи);
// Теперь вызов функции пройдет успешно
Правила = ОбщегоНазначенияВызовСервераПовтИсп.ПолучитьПравилаРегистрацииОбъекта(ПараметрыОбмена);
КонецПроцедуры
Если в процессе отладки выяснилось, что весь прикладной код написан верно, но ошибка продолжает возникать в случайных местах при записи типовых документов, велика вероятность сбоя кэша метаданных платформы 1С. Это часто происходит при скачкообразном изменении режимов совместимости конфигурации в процессе обновления.
Для решения этой проблемы выполним следующие регламентные операции:
srvinfo и удалим папки с временными файлами сеансов./ClearCache.Столкнувшись с ошибкой «Несоответствие типов» при записи документов после повышения режима совместимости до 8.3.11, не спешите переписывать алгоритмы создания документов во внешней обработке. Помните, что корень проблемы кроется в подписках на события конфигурации и строгом контроле параметров в кэшируемых модулях.
Всегда используйте остановку по ошибке в отладчике для быстрого нахождения сбойного модуля и следите за тем, чтобы в параметры функций с повторным использованием возвращаемых значений передавались исключительно ссылки, структуры из простых типов или примитивные значения.