Ситуации, связанные с внезапным отключением электропитания сервера или рабочего компьютера, часто приводят к нарушению логической целостности файловых баз данных 1С. Одной из наиболее неприятных проблем является повреждение данных электронного документооборота (ЭДО) в 1С:Управление нашей фирмой (УНФ). Пользователи сталкиваются с тем, что при попытке открыть, подписать или утвердить входящий документ система выдает критическую ошибку: «Значение не является значением объектного типа (Записать)».
В этой статье мы подробно разберем, почему возникает эта ошибка, как локализовать поврежденную запись с помощью отладчика и какими программными способами можно вернуть работоспособность подсистеме ЭДО.
Проанализируем техническую сторону вопроса. Ошибка обычно указывает на строку кода в общем модуле ОбменСКонтрагентамиВнутренний, где вызывается метод Записать(). Суть проблемы заключается в том, что переменная, к которой применяется этот метод (например, ДанныеЭД), имеет значение Неопределено вместо ожидаемого объекта двоичных данных.
Почему так происходит? При аварийном завершении работы 1С запись в таблице регистрации файлов может сохраниться, но само «тело» файла (хранилище значения) оказывается пустым или поврежденным. Когда система пытается программно извлечь файл из базы для отображения или обработки, она обращается к регистру сведений, находит там строку, но вместо данных получает пустоту. В итоге метод ПолучитьИзВременногоХранилища() или обращение к ресурсу регистра возвращает Неопределено, что и приводит к падению системы при попытке записи этого «ничего» на диск.
Прежде чем приступать к радикальным мерам, нам необходимо точно определить, какой именно объект вызывает сбой. Рассмотрим последовательность действий в режиме отладчика:
ОбменСКонтрагентамиВнутренний на строке, указанной в тексте ошибки (обычно это вызов ДанныеЭД.Записать(ИмяФайла)).ДанныеЭД. Если она равна Неопределено, посмотрим чуть выше по коду, откуда она берет данные.Как правило, данные извлекаются следующим образом:
ДанныеЭД = ПолучитьИзВременногоХранилища(ДопИнформацияПоЭД.СсылкаНаДвоичныеДанныеФайла);
Здесь СсылкаНаДвоичныеДанныеФайла — это ключ, по которому система ищет файл в регистре сведений ДвоичныеДанныеФайлов. Если в отладчике мы видим, что ссылка существует, но данные не получены, значит, мы нашли «битую» запись.
Поскольку стандартные утилиты chdbfl.exe и «Тестирование и исправление» (ТиС) часто не видят логических пустот в полях типа ХранилищеЗначения, нам придется действовать программно. Нам нужно перебрать записи регистра ДвоичныеДанныеФайлов и найти те, которые невозможно прочитать.
Создадим внешнюю обработку и проанализируем ситуацию с помощью следующего алгоритма:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДвоичныеДанныеФайлов.Файл,
| ДвоичныеДанныеФайлов.ДанныеФайла
|ИЗ
| РегистрСведений.ДвоичныеДанныеФайлов КАК ДвоичныеДанныеФайлов";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Попытка
// Пробуем извлечь данные из хранилища
Данные = Выборка.ДанныеФайла.Получить();
Если Данные = Неопределено Тогда
Сообщить("Найден поврежденный файл: " + Выборка.Файл);
// Здесь можно добавить код удаления битой записи
КонецЕсли;
Исключение
Сообщить("Ошибка чтения данных для файла: " + Выборка.Файл);
КонецПопытки;
КонецЦикла;
После выявления проблемных файлов их необходимо удалить из регистра сведений ДвоичныеДанныеФайлов и, возможно, из справочника ПрисоединенныеФайлы. После удаления «битой» ссылки документ ЭДО начнет открываться, хотя само вложение будет отсутствовать. Его можно будет перезапросить у контрагента через сервис ЭДО.
Если документов много и работа стоит, можно применить «быстрое решение» через расширение конфигурации. Мы можем обернуть проблемный участок кода в блок Попытка...Исключение. Рассмотрим, как это сделать:
ОбменСКонтрагентамиВнутренний.СохранитьЭДВФайл и изменим ее код, добавив проверку:
&Вместо("СохранитьЭДВФайл")
Процедура Расш_СохранитьЭДВФайл(ПрисоединенныйФайлСсылка, ПараметрыФайла, КонтекстОперации)
Попытка
// Вызываем оригинальный код или переносим логику с проверкой
ПродолжитьВызов(ПрисоединенныйФайлСсылка, ПараметрыФайла, КонтекстОперации);
Исключение
ЗаписьЖурналаРегистрации("ОшибкиЭДО", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось сохранить файл ЭДО: " + ПрисоединенныйФайлСсылка);
КонецПопытки;
КонецПроцедуры
Важно: Это решение является временным («костылем»), так как оно лишь скрывает симптомы, не устраняя причину — поврежденные данные в базе все равно останутся.
В некоторых случаях помогает метод «перезагрузки» структуры базы данных. Разберем два варианта:
.dt 1С пытается сериализовать все данные. Иногда в процессе обратной загрузки индексы перестраиваются, и некоторые ошибки формата потока исчезают. Однако, если в поле NULL там, где должен быть двоичный код, этот метод не поможет — запись останется пустой.VARBINARY или IMAGE и удалить их напрямую через DELETE.Проанализируем еще несколько моментов, которые могут влиять на появление данной ошибки:
1. Тома хранения файлов. Если в настройках 1С:УНФ включено хранение файлов не в базе данных, а в томах на диске, проверьте физическое наличие файлов в целевой папке. Возможно, из-за сбоя питания файл был создан, но имеет размер 0 КБ. 1С видит запись в базе, пытается прочитать файл с диска, получает пустоту и выдает ошибку.
2. Очистка кэша. Хотя при повреждении данных в таблицах кэш редко является основной причиной, его очистка — обязательный ритуал. Удалите базу из списка и добавьте ее заново или воспользуйтесь параметром запуска /ClearCache.
3. Регистры состояний. Иногда ошибка «залипает» в интерфейсе «Текущие дела ЭДО». Попробуйте проверить регистр сведений СостоянияПоОбъектамУчетаЭДО. Если проблема связана с конкретным документом, можно попробовать временно очистить его статус в этом регистре, чтобы система проигнорировала его при формировании списка.
Подводя итог, отметим: при возникновении ошибки «Значение не является значением объектного типа (Записать)» после отключения света, основным вектором решения является поиск поврежденной записи в регистре ДвоичныеДанныеФайлов и ее удаление. Будьте осторожны и всегда делайте резервную копию базы данных перед выполнением любых программных манипуляций с записями регистров.