Обращение к несуществующему элементу коллекции в 1С 8.3: поиск строки кода и устранение
Содержание
Ошибка «индекс выходит за границы диапазона» в 1С значит одно: код обратился к элементу коллекции по номеру, которого в ней нет. Например, в массиве 3 элемента с индексами 0, 1 и 2, а программа просит Массив[3]. Исправление — найти эту строку кода и добавить проверку количества элементов или поправить границу цикла.
Частое заблуждение — считать, что «сломалась база» и пора запускать тестирование и исправление. На практике в подавляющем числе случаев виновата конкретная строка в модуле: в доработке, внешней обработке, расширении или, реже, в типовой конфигурации на неожиданных данных. В платформе 8.3 текст сообщения обычно звучит как Индекс находится за границами диапазона, в поиске его называют по-разному, но смысл тот же.
Почему 1С выдаёт ошибку индекса: основные причины
Индексы коллекций в 1С 8.3 начинаются с нуля. У массива из 5 элементов последний индекс — 4, а Массив.ВГраница() вернёт именно 4. Любое обращение к индексу меньше нуля или больше ВГраница() даёт ошибку.
Типовые источники:
- 🔢 Сдвиг на единицу. Цикл
Для Сч = 0 По Массив.Количество() Циклделает на один проход больше, чем нужно. - 🗑️ Удаление в прямом цикле. После удаления элемента коллекция короче, а счётчик продолжает расти до старой границы.
- 📭 Пустой результат.
Результат.Выгрузить()[0]падает, если запрос не нашёл ни одной строки. - ✂️ Разбор строки.
СтрРазделить()вернул меньше частей, чем ждал программист: в строке нет разделителя или пустое поле. - 📦 Пакет запросов. Код берёт
Результаты[4], а в пакете после правки осталось 4 запроса. - 📄 Внешние данные. В файле Excel или CSV строка короче остальных: колонок меньше, чем код пытается прочитать.
- 🧩 Чужой код. Расширение или внешняя обработка написаны под старый релиз и ждут другой состав колонок, реквизитов или строк.
Объекты, на которых это встречается чаще всего:
| Коллекция | Как обращаются по индексу | Безопасная граница |
|---|---|---|
| Массив | Массив[Индекс] | от 0 до ВГраница() |
| Таблица значений | ТЗ[Индекс], ТЗ.Получить(Индекс) | от 0 до ТЗ.Количество() - 1 |
| Табличная часть документа | Объект.Товары[Индекс] | от 0 до Количество() - 1 |
| Результаты пакета | Запрос.ВыполнитьПакет()[Индекс] | по числу запросов в тексте |
| Колонки таблицы | ТЗ.Колонки[Индекс] | от 0 до Колонки.Количество() - 1 |
Обращение к отсутствующему ключу у структуры даёт другую ошибку, а соответствие по отсутствующему ключу возвращает Неопределено. Поэтому если в тексте именно «индекс», ищите обращение по номеру.
Как найти строку кода, которая вызывает ошибку индекса
Без точного места исправлять нечего. Порядок действий — от простого к сложному.
1. Прочитать подробный текст ошибки
В окне сообщения нажмите ссылку подробностей. Там будет стек вызовов вида:
{Документ.РеализацияТоваровУслуг.МодульОбъекта(214)}: Индекс находится за границами диапазона
{ОбщийМодуль.ПроведениеСервер.Модуль(1530)}
Первая строка — модуль и номер строки, где случился сбой. Ниже — кто его вызвал. Этого обычно достаточно программисту.
💡 Скопируйте полный текст в письмо или заявку целиком. Фраза «выскакивает ошибка индекса» без стека не даёт ничего.
2. Посмотреть журнал регистрации
Если пользователь закрыл окно, запись остаётся в журнале. В БП 3.0, ЗУП 3.1 и УТ 11 он открывается через Администрирование → Обслуживание → Журнал регистрации. Отберите события с уровнем «Ошибка» за нужный интервал и по пользователю. В комментарии события лежит тот же стек.
3. Поймать ошибку в отладчике
Для разработчика самый быстрый путь:
- Откройте базу в Конфигураторе.
- Запустите отладку:
Отладка → Начать отладку. - Включите
Отладка → Остановка по ошибкеи отметьте нужный вид ошибок или оставьте остановку на всех. - Повторите действие пользователя в запущенном клиенте.
- Отладчик встанет на проблемной строке. В табло посмотрите
Количество()коллекции и значение индекса.
4. Сузить круг, если код недоступен
Пользователю без Конфигуратора помогает метод исключения:
- 🧩 запустить то же действие с отключёнными расширениями (
Администрирование → Печатные формы, отчеты и обработки → Расширения); - 📄 открыть ту же форму типовой командой, а не внешней обработкой;
- 👤 повторить под другим пользователем;
- 📅 повторить на другом документе или за другой период.
Если ошибка пропала после отключения расширения — проблема в нём.
Ошибки в коде с индексами и как их переписать
Ниже — пять шаблонов, которые закрывают большую часть случаев.
Граница цикла
Неправильно — лишний проход:
Для Сч = 0 По Массив.Количество() Цикл
Обработать(Массив[Сч]);
КонецЦикла;
Правильно — граница через ВГраница(). У пустого массива она равна -1, и цикл просто не выполнится:
Для Сч = 0 По Массив.ВГраница() Цикл
Обработать(Массив[Сч]);
КонецЦикла;
Если индекс в теле не нужен, используйте Для Каждого Элемент Из Массив Цикл — там выйти за границу невозможно.
Удаление элементов в цикле
Прямой цикл с удалением пропускает элементы и в конце обращается к индексу, которого уже нет. Удаляйте с конца:
Индекс = Массив.ВГраница();
Пока Индекс >= 0 Цикл
Если НеНужен(Массив[Индекс]) Тогда
Массив.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
Для таблицы значений и табличной части схема та же: обход от Количество() - 1 до 0.
Пустой результат запроса
Код Запрос.Выполнить().Выгрузить()[0].Сумма падает, как только запрос ничего не нашёл. Надёжнее через выборку:
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Сумма = Выборка.Сумма;
Иначе
Сумма = 0;
КонецЕсли;
Разбор строки на части
Части = СтрРазделить(СтрокаФИО, " ", Ложь);
Фамилия = ?(Части.Количество() > 0, Части[0], "");
Имя = ?(Части.Количество() > 1, Части[1], "");
Отчество = ?(Части.Количество() > 2, Части[2], "");
Строка «Иванов Иван» без отчества даёт массив из двух элементов, и прямое Части[2] упало бы.
Пакет запросов
Не берите результат пакета по «магическому» номеру. После того как кто-то добавит временную таблицу в начало текста, Результаты[3] укажет на другой запрос или выйдет за пределы. Варианты:
- 🔍 вынести нужный запрос последним и брать
Результаты[Результаты.ВГраница()]; - 📝 записать номер в переменную с комментарием рядом с текстом запроса и проверять
Результаты.Количество()перед обращением.
Правку типового модуля напрямую в конфигурации делайте только если готовы поддерживать её при каждом обновлении. Для типовых решений правильнее расширение конфигурации: оно переживает обновление релиза.
Ошибка индекса при загрузке файлов и внешних данных
Загрузка из Excel , CSV, текстовых выгрузок банка и маркетплейсов — второй по частоте источник ошибки. Код читает строку, делит её на поля и обращается к полю по номеру.
Что ломает загрузку:
- 📊 в файле удалили или добавили колонку, а обработка ждёт прежний порядок;
- ↩️ в конце файла пустые строки, а код не пропускает их;
- 🔣 в ячейке встретился разделитель (точка с запятой внутри названия товара), и строка разбилась на лишние или недостающие поля;
- 📑 данные лежат не на первом листе, а код читает первый.
Безопасный шаблон для текстовой загрузки:
Поля = СтрРазделить(СтрокаФайла, ";", Истина);
Если Поля.Количество() < 5 Тогда
Сообщить(СтрШаблон("Строка %1 пропущена: полей %2 из 5",
Формат(НомерСтроки, "ЧГ=0"), Формат(Поля.Количество(), "ЧГ=0")));
Продолжить;
КонецЕсли;
Так загрузка не обрывается на всём файле, а сообщает номер проблемной строки. Пользователь правит её и загружает повторно.
💡 Пользователю, у которого падает типовая загрузка: откройте файл, отсортируйте или посмотрите строку, после которой данные не появились в 1С. Почти всегда это пустая строка, объединённые ячейки или лишняя колонка.
Обмены и интеграции
В обменах через правила конвертации и в интеграциях с сайтом картина похожая: приходит пакет, где у объекта меньше строк табличной части или нет ожидаемого элемента. Смотрите протокол обмена: в нём указан объект, на котором прервалась загрузка. Исправление — на стороне отправителя (полнота выгрузки) или в правилах (проверка количества перед обращением).
Когда виноваты база или платформа
Если ошибка возникает в нетронутой типовой конфигурации, расширений нет, а внешние обработки не используются, причина может быть в окружении. Проверяйте в таком порядке:
- Релиз конфигурации. Сравните его с актуальным. Ошибки индекса в типовом коде на редких данных исправляют в следующих релизах, а описание исправлений есть в документации к обновлению.
- Версия платформы. Конфигурация требует номер платформы не ниже указанного в её описании. На старой платформе часть механизмов работает некорректно.
- Кэш клиента. Закройте все сеансы 1С на компьютере пользователя и запустите базу с параметром
/ClearCacheв дополнительных параметрах запуска. Другой вариант — удалить папки кэша в%APPDATA%\1C\1cv8и%LOCALAPPDATA%\1C\1cv8при закрытой программе. - Конфигурация базы данных. Если в Конфигураторе основная конфигурация отличается от конфигурации базы данных, выполните
Конфигурация → Обновить конфигурацию базы данных. Нужен монопольный доступ. - Целостность данных. Тестирование и исправление:
Администрирование → Тестирование и исправлениев Конфигураторе. Для файловой базы есть ещё утилитаchdbfl.exeв папкеbinплатформы; она работает только с закрытой базой.
Перед тестированием и исправлением сделайте резервную копию: процедура меняет данные и может удалить битые ссылки без возможности отката.
Монопольный режим и закрытая файловая база означают, что всем пользователям нужно выйти из программы. Планируйте это на нерабочее время или предупредите людей заранее, иначе несохранённые документы потеряются.
Признак системной причины: ошибка плавает, появляется на разных объектах и пропадает после очистки кэша или перезапуска. Ошибка в коде ведёт себя стабильно — одни и те же данные, одна и та же строка.
Как не допускать выхода индекса за границы
Профилактика держится на нескольких привычках разработчика и пары правил для администратора.
Для разработчика:
- ✅ перебирать коллекции через
Для Каждого, если индекс не нужен; - ✅ для доступа по номеру проверять
Количество()илиВГраница()прямо перед обращением; - ✅ искать строку таблицы через
Найти()илиНайтиСтроки()вместо расчёта номера; - ✅ первую строку результата запроса получать через
Выбрать()иСледующий(); - ✅ при разборе внешних файлов считать поля в каждой строке и пропускать неполные с сообщением;
- ✅ в обработчике
Попытка … Исключениеписать подробности ошибки в журнал регистрации, а не глотать её молча.
Для администратора и ответственного за базу:
- 🧪 проверять внешние обработки и расширения на копии базы после каждого обновления релиза;
- 📋 вести список доработок с указанием, под какой релиз они написаны;
- 📨 требовать от подрядчика проверку на пустых данных: пустой документ, пустой отбор, файл без строк.
Конструкция Попытка … Исключение — не лекарство. Если обернуть ей обращение по индексу и ничего не делать в блоке исключения, документ проведётся с неполными движениями, а ошибку никто не увидит.
Частые вопросы
Можно ли исправить ошибку индекса без программиста?
Почему ошибка появилась только сейчас, хотя обработка работала годами?
Поможет ли обновление платформы?
Почему индекс с нуля, а номер строки в табличной части с единицы?
НомерСтроки — реквизит строки для пользователя, он начинается с 1. Индекс в коллекции начинается с 0. Путаница между ними даёт сдвиг на единицу.