Ошибка «Поле объекта не обнаружено» в 1С означает, что код обратился через точку к реквизиту, колонке или ключу, которого у значения в этот момент нет. Платформа 8.3 пишет имя в скобках — Поле объекта не обнаружено (Склад) — и прерывает выполнение. Проверка синтаксиса в конфигураторе такую ошибку обычно не находит: что лежит в переменной слева от точки, становится известно только при выполнении. Ниже — восемь причин с кодом «было → стало».
Полный текст выглядит так: {Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Форма(112)}: Поле объекта не обнаружено (Склад). В фигурных скобках — модуль, в круглых после него — номер строки, в конце — имя, которое не нашлось. Префикс ВнешняяОбработка или ВнешнийОтчет в имени модуля сразу указывает на подключаемый файл.
В найденной строке возьмите выражение вида Значение.Склад и ответьте на три вопроса:
ТипЗнч().Встроенный язык не различает регистр: объект.склад и Объект.Склад равнозначны. Зато «ё» вместо «е» и латинская буква, похожая на кириллическую, дают другое имя. Латиница попадает в код при копировании с сайтов и наборе в английской раскладке, а в тексте ошибки такое имя выглядит правильным.
// Было: сначала «Поле объекта не обнаружено (СчётУчёта)» — в имени «ё»,
// после исправления — «(Cумма)»: первая «C» набрана латиницей
&НаСервере
Процедура ЗаполнитьСчетаУчетаНаСервере(СчетПоУмолчанию)
Итого = 0;
Для Каждого СтрокаТовары Из Объект.Товары Цикл
СтрокаТовары.СчётУчёта = СчетПоУмолчанию;
Итого = Итого + СтрокаТовары.Cумма;
КонецЦикла;
Объект.СуммаДокумента = Итого;
КонецПроцедуры
// Стало: имена скопированы из дерева метаданных
&НаСервере
Процедура ЗаполнитьСчетаУчетаНаСервере(СчетПоУмолчанию)
Итого = 0;
Для Каждого СтрокаТовары Из Объект.Товары Цикл
СтрокаТовары.СчетУчета = СчетПоУмолчанию;
Итого = Итого + СтрокаТовары.Сумма;
КонецЦикла;
Объект.СуммаДокумента = Итого;
КонецПроцедуры
// Проверка имени из текста ошибки: латиница и «ё» видны по кодам символов
&НаКлиентеНаСервереБезКонтекста
Функция ПодозрительныеСимволы(ИмяПоля)
Найдено = Новый Массив;
Для Позиция = 1 По СтрДлина(ИмяПоля) Цикл
Код = КодСимвола(ИмяПоля, Позиция);
ЭтоЛатиница = (Код >= 65 И Код <= 90) Или (Код >= 97 И Код <= 122);
Если ЭтоЛатиница Или Код = 1025 Или Код = 1105 Тогда // 1025, 1105 — «Ё» и «ё»
Найдено.Добавить(СтрШаблон("«%1» в позиции %2", Сред(ИмяПоля, Позиция, 1), Позиция));
КонецЕсли;
КонецЦикла;
Возврат СтрСоединить(Найдено, "; ");
КонецФункции
// ПодозрительныеСимволы("Cумма") вернёт: «C» в позиции 1
Если имя из ошибки совпадает с реквизитом «на глаз», проверьте его функцией ПодозрительныеСимволы(): поиск по правильному имени строку с латиницей не найдёт. Латиница бывает законной, например в префиксе расширения, поэтому функция только подсказывает.
Типовой код обновляется вместе с метаданными, а падают внешние обработки, расширения и доработки под прошлый релиз. Перед удалением реквизита разработчики типовых обычно переименовывают его с префиксом Удалить. Нашли в дереве УдалитьСклад — данные уже переехали, новое место ищите в описании релиза.
// Было: обработка писалась под прошлый релиз, где Склад был реквизитом шапки.
// В новом релизе склад перенесли в товары — «Поле объекта не обнаружено (Склад)»
&НаСервереБезКонтекста
Функция СкладДокумента(ДокументСсылка)
Возврат ДокументСсылка.Склад;
КонецФункции
// Стало: сначала метаданные, потом чтение оттуда, где склад есть в этом релизе
&НаСервереБезКонтекста
Функция СкладДокумента(ДокументСсылка)
МетаДокумента = ДокументСсылка.Метаданные();
Если МетаДокумента.Реквизиты.Найти("Склад") <> Неопределено Тогда
Возврат ДокументСсылка.Склад;
КонецЕсли;
МетаТовары = МетаДокумента.ТабличныеЧасти.Найти("Товары");
Если МетаТовары = Неопределено Или МетаТовары.Реквизиты.Найти("Склад") = Неопределено Тогда
ВызватьИсключение СтрШаблон("В документе %1 нет реквизита Склад ни в шапке, ни в товарах",
МетаДокумента.Имя);
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = СтрШаблон(
"ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Склад КАК Склад
|ИЗ
| Документ.%1.Товары КАК Т
|ГДЕ
| Т.Ссылка = &Ссылка
|УПОРЯДОЧИТЬ ПО
| Т.НомерСтроки", МетаДокумента.Имя);
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Склад;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Реквизиты.Найти() работает с метаданными в памяти, без обращения к базе. Если склада нет нигде, функция падает с понятным текстом, а не с голым «Поле объекта не обнаружено».
Клиентский код управляемой формы видит данные формы, а не объект базы, и ссылка на клиенте — только идентификатор: её реквизиты через точку не читаются. Код из обычных форм падает на Объект.Контрагент.ИНН и любой «второй точке» вроде Объект.Ссылка.Дата.
// Было: на тонком и веб-клиенте реквизиты по ссылке не читаются —
// «Поле объекта не обнаружено (ИНН)»
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Контрагент) И ПустаяСтрока(Объект.Контрагент.ИНН) Тогда
Сообщить("У контрагента не заполнен ИНН");
КонецЕсли;
КонецПроцедуры
// Стало: реквизит ссылки читается на сервере
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Контрагент) И ПустаяСтрока(ИННКонтрагента(Объект.Контрагент)) Тогда
Сообщить("У контрагента не заполнен ИНН");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ИННКонтрагента(Контрагент)
Возврат Контрагент.ИНН;
КонецФункции
Функция без контекста не передаёт данные формы на сервер, вызов лёгкий. В конфигурациях на БСП внутри неё удобнее ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Контрагент, "ИНН") — она читает одно поле запросом.
В Элементы.Список.ТекущиеДанные есть только поля, выведенные колонками в таблицу формы, и поля с флажком «Использовать всегда». Удалили колонку — код, который её читал, падает.
// Было: колонки «Склад» на форме списка нет, поле не загружено —
// «Поле объекта не обнаружено (Склад)»
&НаКлиенте
Процедура ОткрытьСклад(Команда)
ПоказатьЗначение(, Элементы.Список.ТекущиеДанные.Склад);
КонецПроцедуры
// Стало, вариант 1: у поля Склад реквизита Список включено «Использовать всегда»
&НаКлиенте
Процедура ОткрытьСклад(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ПоказатьЗначение(, ТекущиеДанные.Склад);
КонецПроцедуры
// Стало, вариант 2: реквизиты формы не меняем, склад читаем по ссылке на сервере
&НаКлиенте
Процедура ОткрытьСклад(Команда)
ДокументСсылка = Элементы.Список.ТекущаяСтрока;
Если ДокументСсылка = Неопределено Тогда
Возврат;
КонецЕсли;
ПоказатьЗначение(, СкладПоСсылке(ДокументСсылка));
КонецПроцедуры
&НаСервереБезКонтекста
Функция СкладПоСсылке(ДокументСсылка)
Возврат ДокументСсылка.Склад;
КонецФункции
Флажок ставится в редакторе формы у поля Склад реквизита Список. Второй вариант не трогает реквизиты формы: ТекущаяСтрока списка документов — это ссылка, склад читается по ней на сервере. Проверка на Неопределено защищает от другой ошибки, когда строка не выделена.
Отсутствующий ключ структуры даёт ту же ошибку. Типичные источники — сохранённые настройки старой версии обработки, ответ сервиса из ПрочитатьJSON() и параметры, собранные в разных местах по-разному.
// Было: настройки сохранила прошлая версия обработки, ключа ДатаСреза в них нет —
// «Поле объекта не обнаружено (ДатаСреза)»
&НаСервере
Процедура ВосстановитьНастройки()
Настройки = ХранилищеОбщихНастроек.Загрузить("ВыгрузкаЦен", "Основные");
Если Настройки <> Неопределено Тогда
Объект.Склад = Настройки.Склад;
Объект.ДатаСреза = Настройки.ДатаСреза;
КонецЕсли;
КонецПроцедуры
// Стало: каждый ключ читается через Свойство() со значением по умолчанию
&НаСервере
Процедура ВосстановитьНастройки()
Настройки = ХранилищеОбщихНастроек.Загрузить("ВыгрузкаЦен", "Основные");
Если ТипЗнч(Настройки) <> Тип("Структура") Тогда
Возврат;
КонецЕсли;
Объект.Склад = ЗначениеНастройки(Настройки, "Склад", Объект.Склад);
Объект.ДатаСреза = ЗначениеНастройки(Настройки, "ДатаСреза", НачалоДня(ТекущаяДатаСеанса()));
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЗначениеНастройки(Настройки, Ключ, ЗначениеПоУмолчанию)
Значение = Неопределено;
Если Настройки.Свойство(Ключ, Значение) Тогда
Возврат Значение;
КонецЕсли;
Возврат ЗначениеПоУмолчанию;
КонецФункции
ЗначениеНастройки() не полагается на содержимое второго параметра Свойство() при отсутствии ключа и возвращает умолчание явно. Остальные приёмы работы с ключами — в статье Структура 1С.
У выборки и у таблицы из Выгрузить() есть только поля секции ВЫБРАТЬ, и называются они по псевдонимам после КАК, а не по именам реквизитов.
// Было: «Поле объекта не обнаружено (Цена)» — поля нет в ВЫБРАТЬ;
// после его добавления — «(Сумма)»: в запросе поле названо СуммаСтроки
&НаСервереБезКонтекста
Процедура ВывестиТовары(ДокументСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Номенклатура КАК Номенклатура,
| Т.Количество КАК Количество,
| Т.Сумма КАК СуммаСтроки
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Т
|ГДЕ
| Т.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(СтрШаблон("%1: %2 * %3 = %4", Выборка.Номенклатура,
Выборка.Количество, Выборка.Цена, Выборка.Сумма));
КонецЦикла;
КонецПроцедуры
// Стало: поле есть в ВЫБРАТЬ, обращения идут по псевдонимам после КАК
&НаСервереБезКонтекста
Процедура ВывестиТовары(ДокументСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Номенклатура КАК Номенклатура,
| Т.Количество КАК Количество,
| Т.Цена КАК Цена,
| Т.Сумма КАК СуммаСтроки
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Т
|ГДЕ
| Т.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(СтрШаблон("%1: %2 * %3 = %4", Выборка.Номенклатура,
Выборка.Количество, Выборка.Цена, Выборка.СуммаСтроки));
КонецЦикла;
КонецПроцедуры
В запросе с ОБЪЕДИНИТЬ имена полей берутся из первого запроса: псевдоним, заданный только во втором, в выборке не появится. Если текст собирается по настройкам, проверяйте поле через Результат.Колонки.Найти("Цена") до обхода.
Одно имя может быть в шапке документа, в табличной части или в обоих местах. Код, написанный для документа со складом в строках, падает на документе со складом в шапке, и наоборот.
// Модуль объекта документа
// Было: склад здесь — реквизит шапки, а код ищет его в строке товаров:
// «Поле объекта не обнаружено (Склад)»
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ТоварыНаСкладах.Записывать = Истина;
Для Каждого СтрокаТовары Из Товары Цикл
Движение = Движения.ТоварыНаСкладах.ДобавитьПриход();
Движение.Период = Дата;
Движение.Склад = СтрокаТовары.Склад;
Движение.Номенклатура = СтрокаТовары.Номенклатура;
Движение.Количество = СтрокаТовары.Количество;
КонецЦикла;
КонецПроцедуры
// Стало: реквизиты шапки берутся у документа, колонки — у строки
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ТоварыНаСкладах.Записывать = Истина;
Для Каждого СтрокаТовары Из Товары Цикл
Движение = Движения.ТоварыНаСкладах.ДобавитьПриход();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = СтрокаТовары.Номенклатура;
Движение.Количество = СтрокаТовары.Количество;
КонецЦикла;
КонецПроцедуры
В строке Движение.Склад = СтрокаТовары.Склад имя встречается дважды, и текст ошибки не говорит, у какого значения его нет: регистр без измерения Склад даст то же сообщение. Разнесите выражение на две строки или вычислите обе части в отладчике.
Универсальный код — журнал обмена, групповая обработка, логирование — часто считает, что у любой ссылки есть Код и Наименование. Набор стандартных реквизитов зависит от вида объекта:
| Вид объекта | Стандартные реквизиты | Чего нет |
|---|---|---|
| Справочник | Код, Наименование; Родитель и Владелец — у иерархических и подчинённых | Номер, Дата; Код при нулевой длине кода |
| Документ | Номер, Дата, Проведен, ПометкаУдаления | Код, Наименование, Родитель |
| Перечисление | Реквизитов нет, только представление | Код, Наименование |
// Общий модуль (сервер)
// Было: функция журнала обмена считает, что у любой ссылки есть Код
// и Наименование. На документе: «Поле объекта не обнаружено (Код)»
Функция ОписаниеСсылки(Ссылка) Экспорт
Возврат СокрЛП(Ссылка.Код) + " " + Ссылка.Наименование;
КонецФункции
// Стало: стандартные реквизиты выбираются по виду объекта метаданных
Функция ОписаниеСсылки(Ссылка) Экспорт
МетаОбъекта = Ссылка.Метаданные();
Если Метаданные.Документы.Содержит(МетаОбъекта) Тогда
Возврат СтрШаблон("№ %1 от %2", Ссылка.Номер, Формат(Ссылка.Дата, "ДЛФ=D"));
КонецЕсли;
Если Метаданные.Справочники.Содержит(МетаОбъекта) И МетаОбъекта.ДлинаКода > 0 Тогда
Возврат СокрЛП(Ссылка.Код) + " " + Строка(Ссылка);
КонецЕсли;
// Перечисления, справочники без кода и прочее — платформенное представление
Возврат Строка(Ссылка);
КонецФункции
Метаданные.Документы.Содержит() определяет вид объекта без перебора имён, а Строка(Ссылка) даёт представление любой ссылки, включая перечисления.
Одинаковые по смыслу реквизиты в разных типовых называются по-разному: договор в документах Бухгалтерии 3.0 — ДоговорКонтрагента, в Управлении торговлей 11 — Договор. Обработка, написанная под одну конфигурацию, в другой падает на первом таком обращении.
// Модуль объекта внешней печатной формы (сервер)
// Было: написано под Бухгалтерию 3.0, в УТ 11 —
// «Поле объекта не обнаружено (ДоговорКонтрагента)»
Функция ДанныеДляПечати(ДокументСсылка) Экспорт
Данные = Новый Структура;
Данные.Вставить("Контрагент", ДокументСсылка.Контрагент);
Данные.Вставить("Договор", ДокументСсылка.ДоговорКонтрагента);
Возврат Данные;
КонецФункции
// Стало: имя реквизита выбирается по метаданным из списка вариантов
Функция ДанныеДляПечати(ДокументСсылка) Экспорт
МетаДокумента = ДокументСсылка.Метаданные();
ИмяДоговора = ИмяСуществующегоРеквизита(МетаДокумента, "ДоговорКонтрагента, Договор");
Если ИмяДоговора = "" Тогда
ВызватьИсключение СтрШаблон("Печатная форма не подходит к документу ""%1"": нет реквизита договора",
МетаДокумента.Синоним);
КонецЕсли;
Данные = Новый Структура;
Данные.Вставить("Контрагент", ДокументСсылка.Контрагент);
Данные.Вставить("Договор", ДокументСсылка[ИмяДоговора]);
Возврат Данные;
КонецФункции
Функция ИмяСуществующегоРеквизита(МетаОбъекта, Варианты)
Для Каждого Вариант Из СтрРазделить(Варианты, ",", Ложь) Цикл
Имя = СокрЛП(Вариант);
Если МетаОбъекта.Реквизиты.Найти(Имя) <> Неопределено Тогда
Возврат Имя;
КонецЕсли;
КонецЦикла;
Возврат "";
КонецФункции
Варианты имени собраны в одном месте, проверка идёт по метаданным, а квадратные скобки ДокументСсылка[ИмяДоговора] подставляют имя из переменной. Для одной базы проще отдельная версия под её конфигурацию — универсальность окупается, когда баз несколько.
Попытка.Диагностике мешает Попытка, которая глотает исключение:
// Было: исключение проглочено — модуль, строка и имя поля потеряны
&НаСервере
Процедура ЗагрузитьНаСервере(АдресФайла)
Попытка
ЗагрузитьЦены(АдресФайла); // ваша серверная процедура загрузки
Исключение
Сообщить("Не удалось загрузить цены");
КонецПопытки;
КонецПроцедуры
// Стало: полный текст — в журнал регистрации, первопричина — пользователю
&НаСервере
Процедура ЗагрузитьНаСервере(АдресФайла)
Попытка
ЗагрузитьЦены(АдресФайла);
Исключение
Информация = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("ЗагрузкаЦен", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(Информация));
Сообщить("Не удалось загрузить цены: " + МестоОшибки(Информация));
КонецПопытки;
КонецПроцедуры
&НаКлиентеНаСервереБезКонтекста
Функция МестоОшибки(Информация)
Первопричина = Информация;
Пока Первопричина.Причина <> Неопределено Цикл
Первопричина = Первопричина.Причина;
КонецЦикла;
Возврат СтрШаблон("%1 [%2, строка %3: %4]", Первопричина.Описание, Первопричина.ИмяМодуля,
Формат(Первопричина.НомерСтроки, "ЧГ=0"), СокрЛП(Первопричина.ИсходнаяСтрока));
КонецФункции
Снаружи часто видна обёртка «Ошибка при вызове метода контекста (Записать)», а исходная ошибка лежит в свойстве Причина — МестоОшибки() спускается к ней по цепочке.
Реквизиты.Найти() и ТабличныеЧасти.Найти() в начале процедуры вместо Попытка вокруг каждого обращения.ОбщегоНазначения.ЕстьРеквизитОбъекта(ИмяРеквизита, МетаданныеОбъекта).Свойство() с умолчанием, а набор полей любого значения — через ЗаполнитьЗначенияСвойств в структуру-шаблон: отсутствующие свойства пропускаются без ошибки.Все способы проверки с примерами — в статье Есть свойство объекта 1С.
Порядок одинаковый для ЗУП, Розницы, Бухгалтерии и других типовых:
ВнешняяОбработка или ВнешнийОтчет — виновата подключённая обработка, отчёт или печатная форма. Отключите её в списке дополнительных отчётов и обработок и запросите у автора версию под ваш релиз.Соседние сообщения платформы похожи, но причины у них другие:
| Текст ошибки | Что значит | Пример |
|---|---|---|
| Поле объекта не обнаружено (Имя) | У объекта нет свойства с таким именем | Выборка.Цена без поля в запросе |
| Метод объекта не обнаружен (Имя) | Нет метода, вызванного со скобками | ДокументСсылка.Записать() — записывают объект из ПолучитьОбъект() |
| Значение не является значением объектного типа (Имя) | Слева от точки Неопределено, Null, строка или число | ТекущиеДанные.Склад без выделенной строки, Выборка.Контрагент.ИНН при Null из левого соединения |
| Переменная не определена (Имя) | Ошибка компиляции: имя без точки нигде не объявлено | Несуществующий реквизит шапки в модуле объекта |
| Поле не найдено "Т.Имя" | Ошибка в тексте запроса: поля нет в таблице-источнике | Т.Цена в таблице без такой колонки |
Тип значения слева от точки проверяется через ТипЗнч() — подробнее в статье Тип значения 1С.
Изменились метаданные: реквизит переименовали, перенесли в табличную часть или пометили префиксом Удалить, а внешние обработки, расширения и доработки обращаются к старому имени.
Смотрите модуль в тексте: ВнешнийОтчет — устарел подключённый отчёт. Если модуль типовой, проверьте, повторяется ли ошибка на стандартных настройках варианта. Ошибки в запросе схемы компоновки выглядят иначе — «Поле не найдено».
Только с записью в журнал регистрации и осмысленным значением по умолчанию, иначе ошибка исчезнет из сообщений, а документ запишется с пустым складом. Проверка метаданных заранее надёжнее.
Нет, регистр не учитывается ни в именах реквизитов, ни в ключах структуры, ни в колонках таблицы значений. Ошибку дают «ё» вместо «е» и латиница среди кириллицы.
Если после обновления ошибка всплывает в нескольких обработках или внешнюю печатную форму нужно адаптировать под ваш релиз, быстрее отдать задачу программисту. Опишите её на странице разместить задачу с полным текстом ошибки — оценка бесплатная, направления работ — на странице услуг по доработке 1С.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.