Разработка и Конфигурация · 11 мин
Значение индекса выходит за границы диапазона в 1С: причины и исправление
Разбираем ошибку «Значение индекса выходит за границы диапазона» в 1С: причины, поиск места сбоя, исправление кода и профилактика. Пошаговые действия для пользователя и разработчика.
Ошибка «Значение индекса находится за границами массива» (в диалогах также встречается формулировка «выходит за границы диапазона») — одна из самых частых проблем при работе с 1С. Она возникает, когда программа пытается обратиться к элементу массива, таблицы значений, строки или коллекции по номеру, которого в этой коллекции нет. Например, массив содержит три элемента (индексы 0, 1, 2), а код запрашивает элемент с индексом 3 или -1.
Для пользователя ошибка выглядит как внезапное окно с техническим текстом и прерывание операции: не проводится документ, не формируется отчёт, не открывается форма. Для разработчика это сигнал о логической ошибке в алгоритме — чаще всего в цикле, при разборе строки или при обращении к результату запроса, который оказался пустым.
Хорошая новость в том, что ошибка почти всегда локализуема: платформа указывает строку модуля, где произошло обращение за границу коллекции. Зная это место и понимая типичные сценарии, проблему можно устранить за короткое время, не прибегая к переустановке программы или восстановлению базы.
Что означает ошибка и когда она возникает
В 1С индексация коллекций начинается с нуля. Первый элемент массива имеет индекс 0, последний — «Количество() минус 1». Любое обращение вне этого интервала вызывает исключение. Это касается массивов, таблиц значений, табличных частей документов, строк (при обращении к символу), результатов разбора строки функцией СтрРазделить и других коллекций.
Типичные ситуации появления ошибки:
- цикл проходит на одну итерацию больше, чем нужно, из-за неверного условия окончания;
- код обращается к первому элементу результата запроса, который вернул пустую выборку;
- строка разбивается по разделителю, но частей оказалось меньше, чем ожидал алгоритм;
- после удаления строк из табличной части сохранённый ранее индекс стал недействительным;
- обмен данными или загрузка из файла привели к структуре, отличной от ожидаемой.
Как найти место ошибки в коде
Текст сообщения об ошибке обычно содержит указание на модуль и номер строки, например: «{Документ.РеализацияТоваровУслуг.МодульОбъекта(145)}: Значение индекса находится за границами массива». Число в скобках — это номер строки в указанном модуле. Именно с этой строки начинается диагностика.
Порядок поиска места сбоя:
- Скопируйте полный текст ошибки или сфотографируйте окно до нажатия «ОК».
- Откройте конфигуратор и найдите указанный объект и модуль.
- Перейдите к строке с указанным номером (Ctrl+G или меню «Правка — Перейти к строке»).
- Определите, к какой коллекции идёт обращение в этой строке, и проследите, откуда берётся индекс.
Если ошибка возникает нестабильно и воспроизвести её сложно, подключите отладку: запустите конфигуратор в режиме отладки, поставьте точку останова в проблемном месте и повторите действия пользователя. В момент останова посмотрите в табло значение индекса и размер коллекции — расхождение будет видно сразу.
- 1Зафиксируйте полный текст ошибки с именем модуля и номером строки
- 2Откройте указанный модуль в конфигураторе и перейдите к строке
- 3Определите коллекцию и источник значения индекса
- 4Проверьте размер коллекции через Количество() или ВГраница() в отладчике
- 5Исправьте логику: границы цикла или добавьте проверку перед обращением
- 6Повторите сценарий и убедитесь, что ошибка исчезла
Типичные сценарии и способы исправления
Ошибка в цикле перебора коллекции
Самый распространённый случай — цикл с ручным управлением индексом. Классическая ошибка — использование Количество() как верхней границы включительно:
// Неправильно: последняя итерация даст индекс за границей
Для Инд = 0 По Массив.Количество() Цикл
Значение = Массив[Инд];
КонецЦикла;
// Правильно
Для Инд = 0 По Массив.Количество() - 1 Цикл
Значение = Массив[Инд];
КонецЦикла;
Более надёжная альтернатива — цикл «Для Каждого», который вообще исключает ручную работу с индексами:
Для Каждого Элемент Из Массив Цикл
// работа с Элемент напрямую
КонецЦикла;
Обращение к пустому результату запроса или разбору строки
Код вида «Выборка[0]» или «ЧастиСтроки[1]» без проверки, что элементы вообще есть, — второй по частоте источник проблемы. Перед обращением по индексу всегда проверяйте размер:
Части = СтрРазделить(ВходнаяСтрока, ";");
Если Части.Количество() >= 2 Тогда
ВтороеПоле = Части[1];
Иначе
// обработка ситуации: частей меньше, чем ожидалось
КонецЕсли;
Удаление строк и устаревшие индексы
Если в цикле удаляются строки таблицы значений или табличной части, индексы оставшихся элементов сдвигаются. Обход «вперёд» при удалении гарантированно ведёт либо к пропуску строк, либо к выходу за границу. Безопасные приёмы — обход с конца к началу или сбор строк на удаление в отдельный массив с последующим удалением вне цикла обхода.
Что делать пользователю без доступа к коду
Если вы работаете в типовой конфигурации и не занимаетесь доработками, самостоятельно исправить код вы не сможете, но можете сузить круг причин и подготовить информацию для специалиста. Начните с простых шагов, которые часто решают проблему без вмешательства в код.
Во-первых, проверьте, не устарела ли конфигурация: многие подобные ошибки исправляются в обновлениях. Во-вторых, проанализируйте данные, с которыми выполнялась операция: пустые реквизиты, незаполненные табличные части, документы с необычными значениями нередко провоцируют сбой в типовых алгоритмах. В-третьих, очистите кэш метаданных пользователя — повреждённый кэш иногда вызывает ошибки, не связанные с реальной логикой.
Как выбрать действие
Проверка результата и профилактика
После исправления кода недостаточно один раз запустить операцию — нужно проверить граничные случаи, которые и вызывали сбой: пустые коллекции, коллекции из одного элемента, максимально длинные наборы данных. Именно на границах диапазонов живут подобные ошибки.
Полезные приёмы профилактики при разработке:
- используйте «Для Каждого» вместо индексных циклов, где не нужен сам индекс;
- перед обращением по индексу проверяйте Количество() или используйте метод ВГраница() для массивов;
- после СтрРазделить и подобных функций всегда проверяйте число полученных частей;
- не храните индексы строк между операциями, изменяющими коллекцию — храните сами строки или их ключевые значения;
- покрывайте алгоритмы, работающие с коллекциями, проверками на пустые и минимальные наборы данных.
Как проверить результат
Операция завершается штатно, данные корректны
Ошибка повторяется или появляется другое исключение
Код отрабатывает без обращения по индексу, срабатывает ветка проверки
Снова возникает ошибка выхода за границы
Обрабатывается ровно один элемент, цикл завершается корректно
Лишняя итерация или пропуск единственного элемента
Когда обращаться к специалисту и что ему передать
Есть ситуации, где самостоятельное вмешательство нежелательно: конфигурация на поддержке без возможности изменения, ошибка в механизмах обмена с риском рассинхронизации данных, либо сбой воспроизводится в регламентных операциях, затрагивающих учётные данные. В этих случаях правильнее передать задачу разработчику или в поддержку вендора.
Чтобы специалист решил проблему быстро, подготовьте: полный текст ошибки с указанием модуля и строки, последовательность действий до сбоя, сведения о релизе конфигурации и платформы, а также пример данных (документа, элемента справочника), на котором ошибка воспроизводится. Скриншот окна ошибки и журнал регистрации за момент сбоя заметно ускоряют диагностику.
Помните и о технологическом журнале: если ошибка плавающая и не воспроизводится в отладчике, настройте запись событий EXCP в технологическом журнале — это даст стек вызовов и контекст в момент реального сбоя на рабочем сервере.
Что важно запомнить
Ошибка выхода индекса за границы диапазона всегда означает обращение к несуществующему элементу коллекции. Диагностика начинается со строки модуля из текста ошибки, исправление — с проверки размера коллекции и границ цикла. Проверяйте результат на пустых и минимальных наборах данных, а любые правки выполняйте только на копии базы.
Частые вопросы
Ошибка возникает только у одного пользователя, у остальных всё нормально. В чём причина?
Чаще всего это повреждённый локальный кэш метаданных. Удалите базу из списка информационных баз пользователя и добавьте её заново, либо очистите папку кэша в каталоге данных пользователя. Если не помогло — проверьте, не связана ли ошибка с настройками или данными, доступными только этому пользователю.
Можно ли просто обернуть проблемный код в Попытка/Исключение?
Технически можно, но это плохая практика: исключение замаскирует реальную причину, и ошибка проявится позже в другом месте или приведёт к некорректным данным. Конструкцию Попытка/Исключение стоит применять для ожидаемых внешних сбоев (недоступность сервиса, файл), а не для подавления логических ошибок индексации.
Ошибка появляется в типовой конфигурации без доработок. Кто виноват?
Возможны три варианта: известная ошибка релиза (проверьте обновления и описания исправлений), некорректные данные, введённые в базу (пустые или необычные значения, на которых типовой алгоритм не рассчитан), либо повреждение кэша. Начните с очистки кэша и обновления, затем анализируйте данные.
Как быстро проверить массив перед обращением к элементу?
Используйте сравнение размера: «Если Массив.Количество() > Индекс Тогда». Для массивов также удобен метод ВГраница(), возвращающий максимально допустимый индекс: условие «Индекс <= Массив.ВГраница()» гарантирует, что обращение будет корректным.
Ошибка возникает при обмене данными или загрузке файла. Что проверить в первую очередь?
Проверьте структуру входящих данных: состав полей, разделители, количество колонок в файле могли измениться на стороне источника. Код загрузки, рассчитанный на фиксированное число частей, падает именно при расхождении структуры. Сравните актуальный файл с эталонным, который загружался успешно.
Нужно ли запускать тестирование и исправление базы при этой ошибке?
Нет, эта ошибка относится к логике кода, а не к повреждению данных. Тестирование и исправление её не устранит. Запускать эту процедуру имеет смысл только если есть независимые признаки повреждения базы: сбои при чтении таблиц, ошибки СУБД, внезапные отключения сервера перед появлением проблемы.