Почему возникает ошибка «Значение поля Номер не уникально» при записи бизнес-процесса в 1С и как ее исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Документооборот IT и автоматизация бизнеса
← На главную

При автоматическом создании, старте или записи бизнес-процессов и связанных с ними объектов разработчики нередко сталкиваются с неприятной ситуацией: платформа 1С:Предприятие генерирует исключение «Значение "..." поля "Номер" не уникально». Особенность этой ошибки часто заключается в том, что при каждой следующей попытке номер автоматически инкрементируется (увеличивается на единицу), но запись всё равно завершается аварийно. Разберем детально, почему это происходит, в каких объектах на самом деле возникает коллизия и как по шагам восстановить корректную работу механизма нумерации.

Причины возникновения коллизий нумерации

Для эффективного устранения неполадки выясним внутреннюю механику работы нумераторов платформы 1С. В большинстве случаев ошибка вызвана одной из следующих причин:

  1. Рассинхронизация кэша номеров кластера серверов 1С. В целях оптимизации производительности рабочий процесс rphost заранее резервирует диапазон свободных номеров. Если информационная база была восстановлена из резервной копии СУБД (например, средствами Microsoft SQL Server или PostgreSQL) без перезапуска службы сервера 1С (ragent), кэш считает свободными те номера, которые уже записаны в СУБД.
  2. Скрытая ошибка во вложенных процессах или задачах. Текст системной ошибки платформы сообщает только значение проблемного номера, но не указывает имя таблицы метаданных. При старте бизнес-процесса в рамках одной системной транзакции создаются подчиненные задачи (Задачи.ЗадачаИсполнителя) или вложенные бизнес-процессы. Номер может быть занят именно в подчиненной таблице, а не в основном бизнес-процессе.
  3. Некорректная логика в обработчике ПередСозданиемВложенныхБизнесПроцессов. Если разработчик вручную вызывает метод Записать() или Старт() для подчиненного процесса, а затем платформа пытается выполнить штатную запись объекта по карте маршрута, происходит повторная попытка захвата того же номера в одной транзакции.
  4. Нарушение длины номера, ведущих нулей или наличие «хвостов» нумерации. Если пользователь или внешняя обработка записали номер без лидирующих нулей (например, 2809147 вместо 002809147) либо создали документ с номером из далекого будущего диапазона, строковое сравнение платформы сбивается, натыкаясь на занятые позиции при каждом последующем шаге автоинкремента.

Шаг 1. Локализация проблемной таблицы и поиск занятого номера

Проанализируем данные информационной базы, чтобы точно выяснить, какой объект метаданных вызывает исключение. Для этого выполним запрос через консоль запросов или внешнюю обработку сразу по нескольким таблицам, которые участвуют в маршруте бизнес-процесса.

Посмотрим на пример диагностического запроса:


ВЫБРАТЬ
    "Основной процесс" КАК ТипОбъекта,
    БП.Ссылка КАК Ссылка,
    БП.Номер КАК Номер,
    БП.Дата КАК Дата
ИЗ
    БизнесПроцесс.Согласование КАК БП
ГДЕ
    БП.Номер ПОДОБНО "%280914%"

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Вложенный процесс",
    Вложенный.Ссылка,
    Вложенный.Номер,
    Вложенный.Дата
ИЗ
    БизнесПроцесс.Утверждение КАК Вложенный
ГДЕ
    Вложенный.Номер ПОДОБНО "%280914%"

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Задачи исполнителей",
    Задачи.Ссылка,
    Задачи.Номер,
    Задачи.Дата
ИЗ
    Задача.ЗадачаИсполнителя КАК Задачи
ГДЕ
    Задачи.Номер ПОДОБНО "%280914%"

Данный запрос позволяет сразу определить, в какой именно таблице уже существует объект с конфликтующим номером. Часто оказывается, что номер занят не в основном процессе, а в создаваемой платформой задаче.

Шаг 2. Обновление кэша нумерации объектов

Если база данных недавно восстанавливалась из бэкапа или в кластере серверов произошел сбой, необходимо принудительно обновить нумерацию. Метод глобального контекста ОбновитьНумерациюОбъектов() без параметров сбрасывает кэш для всей базы, однако надежнее вызывать его точечно для конкретных метаданных.

Разберем программный пример сброса кэша для бизнес-процессов и задач:


// Сброс кэша для основного процесса
ОбновитьНумерациюОбъектов(Метаданные.БизнесПроцессы.Согласование);

// Сброс кэша для вложенного процесса
ОбновитьНумерациюОбъектов(Метаданные.БизнесПроцессы.Утверждение);

// Сброс кэша для задач
ОбновитьНумерациюОбъектов(Метаданные.Задачи.ЗадачаИсполнителя);

Сообщить("Кэш нумерации объектов успешно обновлен.");

Если выполнение метода в пользовательском режиме не помогло избавиться от ошибки на стороне сервера, выполним перезапуск службы 1C:Enterprise Server Agent (ragent) в диспетчере служб операционной системы. Это гарантированно очистит внутреннюю память всех рабочих процессов rphost.

Шаг 3. Проверка программного кода в точке маршрута

Рассмотрим типовую ошибку при работе с обработчиком события ПередСозданиемВложенныхБизнесПроцессов на карте маршрута бизнес-процесса. Платформа самостоятельно управляет жизненным циклом и транзакцией создания подчиненных процессов.

Посмотрим на пример ошибочного и корректного заполнения параметров вложенного процесса:


// ОШИБОЧНЫЙ ВАРИАНТ:
// Ручное создание и запись вызывают конфликт номеров в системной транзакции
Процедура ВложенныйПроцессПередСозданием(ТочкаМаршрутаБизнесПроцесса, ФормируемыеБизнесПроцессы, Отказ)
    
    НовыйПроцесс = БизнесПроцессы.Утверждение.СоздатьБизнесПроцесс();
    НовыйПроцесс.Дата = ТекущаяДатаСеанса();
    НовыйПроцесс.ГлавнаяЗадача = ТочкаМаршрутаБизнесПроцесса;
    // ОШИБКА: метод Записать() здесь вызывать нельзя!
    НовыйПроцесс.Записать(); 
    
КонецПроцедуры

// КОРРЕКТНЫЙ ВАРИАНТ:
// Настройка переданных платформой объектов без явной записи
Процедура ВложенныйПроцессПередСозданиемКорректно(ТочкаМаршрутаБизнесПроцесса, ФормируемыеБизнесПроцессы, Отказ)
    
    Для Каждого Процесс Из ФормируемыеБизнесПроцессы Цикл
        Процесс.Дата = ТекущаяДатаСеанса();
        Процесс.Предмет = ЭтотОбъект.Предмет;
        Процесс.Автор = ЭтотОбъект.Автор;
        // Запись и старт процесса платформа выполнит автоматически
    КонецЦикла;
    
КонецПроцедуры

Обратим внимание на то, что если в коде требуется программно переопределить или сформировать номер, следует использовать метод УстановитьНовыйНомер() вместо прямой модификации строкового реквизита Номер.


// Корректная программная инициализация номера
ОбъектПроцесс = БизнесПроцессы.Согласование.СоздатьБизнесПроцесс();
ОбъектПроцесс.Дата = ТекущаяДатаСеанса();
ОбъектПроцесс.УстановитьНовыйНомер();
ОбъектПроцесс.Записать();

Шаг 4. Устранение нарушений в формате номеров и перенумерация

Если в базе присутствуют записи с нарушенной структурой номера (пропущены лидирующие нули, введены недопустимые символы вручную), платформа не может корректно рассчитать следующий номер по порядку.

Разберем алгоритм восстановления целостности нумерации:

  1. Проверить периодичность нумератора. Откроем конфигуратор и проверим свойства объекта метаданных. Если установлена периодичность (например, В пределах года), проверим дату создаваемого объекта. Если дата пустая (01.01.0001), платформа ищет свободный номер в нулевом периоде, где уже могут быть зафиксированы старые ошибочные записи.
  2. Найти записи с максимальными номерами. Выполним сортировку списка процессов по убыванию поля Номер. Проверим, нет ли в конце списка некорректных номеров с девятками (999999999) или тестовых записей.
  3. Выполнить групповую перенумерацию. Воспользуемся стандартной обработкой Универсальный подбор и обработка объектов или специализированной обработкой Перенумерация объектов, чтобы привести все номера к единому виду с лидирующими нулями и правильными префиксами узлов РИБ или организаций.
  4. Повторно инициализировать автонумератор. После исправления номеров обязательно вызовем метод ОбновитьНумерациюОбъектов(), чтобы сервер 1С зафиксировал новое максимальное значение в таблицах базы данных.

Соблюдение этих правил и последовательная диагностика позволяют быстро устранить блокирующую ошибку уникальности номера и обеспечить стабильное прохождение маршрутов бизнес-процессов в 1С.

← На главную