Индекс вышел за границы массива в 1С 8.3: найти строку кода и устранить сбой

· 9 мин

Содержание

Ошибка «индекс за границами массива» в 1С означает одно: код обратился к элементу коллекции по номеру, которого в ней нет. Например, в массиве 3 элемента (индексы 0, 1, 2), а программа просит Массив[3]. Исправление — найти эту строку через подробный текст ошибки или отладчик и добавить проверку количества элементов перед обращением.

Типичная ситуация: бухгалтер нажимает «Провести» или «Заполнить», а на экране Индекс находится за границами диапазона. Вчера тот же документ проводился. Значит, данные стали другими: пустая табличная часть, строка без разделителя, на одну позицию меньше. Код к этому не готов.

Что означает сообщение и как оно выглядит в 1С 8.3

Платформа 1С:Предприятие 8.3 пишет дословно Индекс находится за границами диапазона. В поиске эту ошибку чаще ищут как «индекс за границами массива», но речь об одном и том же.

Ошибка возникает не только у массивов. Она появляется при обращении по индексу к любой индексируемой коллекции:

  • 📦 Массив и ФиксированныйМассив;
  • 📋 ТаблицаЗначений и её строки: Таблица[5];
  • 🧾 табличная часть документа или справочника: Объект.Товары[0];
  • 🔤 результат СтрРазделить(): Части[2];
  • 🗂 СписокЗначений, коллекция колонок, коллекция строк дерева.

Главное правило, без которого ошибку не понять: индексы в 1С начинаются с нуля. У коллекции из N элементов последний индекс равен N − 1. Метод ВГраница() у массива возвращает именно этот последний индекс, а у пустого массива — -1.

КоллекцияЭлементовДопустимые индексыПоследний индекс
Массив из 3 элементов30, 1, 22
Пустая табличная часть0нетобращаться нельзя
СтрРазделить("А;Б", ";")20, 11

Почему индекс выходит за границы массива: пять причин

1. Ошибка на единицу в цикле

Самая частая причина в самописном коде. Цикл идёт до Количество(), а не до Количество() - 1:

Для Индекс = 0 По Массив.Количество() Цикл
    Сообщить(Массив[Индекс]); // на последнем шаге индекс = Количество()
КонецЦикла;

2. Обращение к первой строке пустой коллекции

Код уверен, что строка есть: Объект.Товары[0].Номенклатура. Для документа без товаров это падение. Так же ломается Запрос.Выполнить().Выгрузить()[0], когда запрос ничего не вернул.

3. Удаление элементов в цикле со счётчиком

В 1С граница цикла Для … По … вычисляется один раз, при входе в цикл. Если внутри удалять элементы, коллекция укорачивается, а счётчик продолжает идти до старой границы. На последних шагах индекс указывает в пустоту.

4. Разбор строки с непредсказуемым форматом

Загрузка из файла или обмена: строка "Иванов;Пётр" разбирается в расчёте на три поля, а пришло два. СтрРазделить(Стр, ";")[2] сразу даёт ошибку. В типовых обработках загрузки это часто всплывает на одной «кривой» строке файла.

5. Рассинхрон двух коллекций

Код идёт по индексам одного массива и берёт по тем же индексам значения из другого. Пока массивы одинаковой длины, всё работает. Добавили элемент в один — второй отстаёт, и на последнем шаге индекс выходит за его пределы.

Диагностика: выберите симптом

Как найти строку с ошибкой: три способа диагностики

Пока не известна строка кода, исправлять нечего. Начните с самого быстрого способа.

Способ 1. Подробный текст ошибки

В окне ошибки 1С 8.3 нажмите ссылку для подробностей. Появится текст вида:

{Документ.РеализацияТоваровУслуг.МодульОбъекта(214)}: Индекс находится за границами диапазона

В фигурных скобках — объект, модуль и номер строки. Ниже идёт стек: какие процедуры вызывали друг друга. Скопируйте этот текст целиком. Его достаточно, чтобы программист открыл модуль и перешёл к строке.

💡 Если в пути стоит имя расширения или внешней обработки, причина в доработке, а не в типовой конфигурации.

Способ 2. Отладчик с остановкой по ошибке

Способ для тех, у кого есть доступ к Конфигуратору:

  1. Откройте базу в Конфигураторе.
  2. Запустите отладку: Отладка → Начать отладку (F5).
  3. В Конфигураторе включите Отладка → Остановка по ошибке и отметьте остановку при любой ошибке.
  4. Повторите действие в пользовательском режиме.
  5. Отладчик остановится ровно на проблемной строке.

Дальше откройте Отладка → Стек вызовов (Ctrl+Alt+C), чтобы понять, откуда пришёл вызов. Выделите переменную и нажмите Shift+F9: окно «Вычислить выражение» покажет Массив.Количество() и текущее значение индекса. Расхождение видно сразу.

В клиент-серверной базе серверный код отлаживается, только если сервер 1С разрешает отладку. Включение отладки на сервере требует перезапуска службы — это обрывает сеансы всех пользователей. Делайте это в нерабочее время или на копии базы.

Способ 3. Журнал регистрации

Если ошибку видел пользователь, а вы — нет, откройте журнал регистрации: Администрирование → Обслуживание → Журнал регистрации (в Конфигураторе — Администрирование → Журнал регистрации). Отберите события с уровнем «Ошибка» за нужное время и по пользователю. В записи будет тот же текст с модулем и строкой.

СпособКогда подходитЧто нужно
Подробный текст ошибкиОшибка воспроизводится у пользователяНичего, только окно ошибки
ОтладчикНужно увидеть значения переменныхКонфигуратор, права администратора
Журнал регистрацииОшибка была раньше, повторить сложноПрава на просмотр журнала

Исправление индекса за границами массива пошагово

Когда строка найдена, порядок действий такой.

Шаг 1. Проверьте данные

Сначала посмотрите на сам документ или файл. Пустая табличная часть, документ без строк, файл с неполной строкой — частый корень проблемы. Иногда достаточно заполнить данные правильно, и код не трогать.

Шаг 2. Определите, какой индекс и какая длина

В отладчике вычислите оба значения. Если индекс равен количеству — это ошибка на единицу. Если коллекция пустая — нужна проверка перед обращением. Если длина «внезапно» меньше — ищите удаление в цикле.

Шаг 3. Внесите исправление

СитуацияИсправление
Цикл до Количество()Граница Количество() - 1 или ВГраница()
Обход всех элементовЦикл Для Каждого … Из … без индексов
Пустая коллекцияПроверка Количество() > 0 или Количество() = 0
Удаление в циклеОбратный цикл от последнего элемента
Разбор строкиПроверка числа частей после СтрРазделить()

Шаг 4. Проверьте на копии

Повторите исходное действие на копии базы с теми же данными. Проверьте и граничные случаи: пустая таблица, одна строка, много строк.

В типовую конфигурацию на поддержке исправления лучше вносить через расширение, а не снимать конфигурацию с поддержки. Так правка переживёт обновление релиза.

Если ошибка в типовой конфигурации

Бывает, что в подробном тексте ошибки указан типовой модуль, а доработок в базе нет. Порядок такой:

  1. 🔎 Проверьте данные. Типовой код рассчитан на корректные данные, а битая или неполная информация в документе его ломает.
  2. 🔄 Сравните релиз конфигурации с актуальным. Подобные ошибки разработчики исправляют в новых релизах.
  3. 🧩 Отключите расширения и внешние обработки на копии базы и повторите действие. Если ошибка ушла, виновата доработка.
  4. 🛠 Запустите тестирование и исправление информационной базы на копии, если подозреваете повреждение данных.

Тестирование и исправление запускайте только после резервной копии. Оно требует монопольного режима: все пользователи должны выйти из базы.

Если ничего не помогло, отправьте подробный текст ошибки и номер релиза в поддержку вашего партнёра 1С или разработчику доработки. Текст со стеком вызовов экономит им несколько итераций переписки.

Примеры кода до и после исправления

Цикл с ошибкой на единицу

До:

Для Индекс = 0 По Массив.Количество() Цикл
    Итог = Итог + Массив[Индекс];
КонецЦикла;

После:

Для Каждого Значение Из Массив Цикл
    Итог = Итог + Значение;
КонецЦикла;

Если индекс всё же нужен, граница — Массив.ВГраница(). Для пустого массива это -1, и цикл Для Индекс = 0 По -1 не выполнится ни разу.

Первая строка табличной части

До:

Номенклатура = Объект.Товары[0].Номенклатура;

После:

Номенклатура = Неопределено;
Если Объект.Товары.Количество() > 0 Тогда
    Номенклатура = Объект.Товары[0].Номенклатура;
КонецЕсли;

Удаление элементов в цикле

До:

Для Индекс = 0 По Массив.ВГраница() Цикл
    Если Массив[Индекс] = 0 Тогда
        Массив.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Граница вычислена один раз. Удалили один элемент — последний шаг обратится к несуществующему индексу.

После, обратный цикл:

Всего = Массив.Количество();
Для Сч = 1 По Всего Цикл
    Индекс = Всего - Сч;
    Если Массив[Индекс] = 0 Тогда
        Массив.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Проверим на массиве из 4 элементов: индексы идут 3, 2, 1, 0. Удаление элемента с индексом 3 не сдвигает элементы 0–2, поэтому следующие обращения корректны.

Разбор строки из файла

До:

Части = СтрРазделить(СтрокаФайла, ";");
ИНН = Части[2];

После:

Части = СтрРазделить(СтрокаФайла, ";");
Если Части.Количество() < 3 Тогда
    ТекстОшибки = СтрШаблон("Строка %1: ожидалось 3 поля, получено %2",
        Формат(НомерСтроки, "ЧГ=0"), Формат(Части.Количество(), "ЧГ=0"));
    Сообщить(ТекстОшибки);
    Продолжить;
КонецЕсли;
ИНН = Части[2];

Код не падает на всём файле, а сообщает номер плохой строки и идёт дальше. Пример предполагает, что он стоит внутри цикла по строкам файла, где есть переменная НомерСтроки.

Результат запроса

До:

Цена = Запрос.Выполнить().Выгрузить()[0].Цена;

После:

Выборка = Запрос.Выполнить().Выбрать();
Цена = 0;
Если Выборка.Следующий() Тогда
    Цена = Выборка.Цена;
КонецЕсли;

Выборка не требует индекса и не выгружает таблицу целиком, поэтому ещё и быстрее.

Чего не делать при исправлении

Несколько «исправлений», которые убирают сообщение, но оставляют проблему:

  • ❌ Обернуть всё в Попытка … Исключение с пустым обработчиком. Ошибка пропадёт, но документ проведётся с неполными данными, и никто не узнает почему. Если попытка нужна, хотя бы запишите ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()) в журнал регистрации.
  • ❌ Сдвинуть границу «на всякий случай» до Количество() - 2. Последний элемент перестанет обрабатываться, и итоги разойдутся.
  • ❌ Править типовой модуль напрямую. Правка потеряется при обновлении или усложнит его. Используйте расширение.
  • ❌ Исправлять в рабочей базе без проверки. Новая проверка может пропустить другую ветку кода. Сначала копия.

Как писать код без выхода за границы массива

Профилактика проще отладки. Несколько привычек снимают почти все случаи:

  • ✅ Для обхода всех элементов используйте Для Каждого. Индексы там не нужны, ошибиться в границе невозможно.
  • ✅ Перед [0] всегда проверяйте Количество(). Пустые табличные части и пустые результаты запросов — нормальное состояние данных.
  • ✅ Удаляйте элементы обратным циклом или собирайте «что удалить» в отдельный массив и удаляйте после обхода.
  • ✅ Данные извне (файлы, обмены, ответы сервисов) проверяйте на число полей до разбора.
  • ✅ Не держите параллельные массивы. Удобнее одна таблица значений с колонками или структура в каждом элементе.
  • ✅ Для поиска строки используйте Найти() или НайтиСтроки() с проверкой результата на Неопределено или пустоту, а не перебор по индексу.
Перед сдачей кода с индексами
Выполнено: 0 / 5

Частые вопросы

Почему ошибка появляется не у всех пользователей?
Код один, а данные разные. У одного пользователя документ с пустой табличной частью или другой набор отборов, у другого — нет. Ищите отличие в данных.
Чем ВГраница() отличается от Количество()?
Количество() возвращает число элементов, ВГраница() — индекс последнего. Для массива из 5 элементов это 5 и 4, для пустого — 0 и −1.
Можно ли получить элемент массива без риска ошибки?
Метод Получить() при неверном индексе тоже выдаёт ошибку. Безопасный путь — проверить индекс: Если Индекс <= Массив.ВГраница() Тогда.
Ошибка возникает в обработке с сайта. Что делать?
Сначала проверьте, для вашей ли конфигурации и релиза написана обработка. Если подробный текст ошибки указывает на её модуль, обратитесь к автору с этим текстом или откажитесь от обработки.
Помогает ли очистка кэша или перезапуск 1С?
Нет. Это ошибка логики кода на конкретных данных. Перезапуск ничего не меняет, пока данные и код прежние.