Функция может успешно запускаться вручную и падать из триггера, потому что контекст авторизации и аргумент события отличаются. После копирования формы, смены владельца или привязанной таблицы старый trigger продолжает смотреть на другой источник либо теряет разрешения.
Не вызывайте обработчик кнопкой Run как единственную проверку: у ручного запуска нет настоящего form-submit event. Откройте executions, найдите время тестовой отправки, владельца запуска, функцию, статус и stack trace. Создавайте новый ответ только с тестовыми данными.
Что проверить в первую очередь
Для проблемы «Apps Script перестал обрабатывать новые ответы Google Forms» сначала зафиксируйте один воспроизводимый пример: точное время, идентификатор объекта, пользователя или операции, входные данные, версию приложения и фактический результат. Отдельно запишите ожидаемое поведение: установленный триггер принадлежит действующей учётной записи, получает правильный event object, фиксирует результат каждой заявки и безопасно повторяет временные ошибки. Это не формальность. Без исходной точки легко принять временное совпадение за исправление, изменить сразу несколько условий и потерять возможность доказать настоящую причину сбоя.
Проверку начинайте с чтения состояния и журналов. Не запускайте массовый перерасчёт, повторную отправку, удаление записей или изменение прав на рабочей системе, пока не подготовлены резервная копия и способ отката. Секреты, токены, персональные данные и содержимое заказов в диагностические выгрузки не включайте.
- Уточните, к чему привязан скрипт: форме, таблице ответов или standalone-проекту.
- Проверьте тип установленного триггера и идентификатор источника.
- Сверьте владельца trigger и доступ этой учётной записи к форме, таблице, Drive, Gmail и внешнему API.
- Посмотрите квоты и незавершённые authorization requests.
- Проверьте структуру event.namedValues или event.response для выбранного типа события.
Почему возникает проблема
Видимый симптом обычно находится в конце цепочки. Пользователь видит неверный статус или отказ, хотя первичная ошибка могла произойти в API, фоновой задаче, кеше, очереди, внешнем сервисе либо при проверке доступа. Основной риск этого сценария: заявки остаются без обработки, уведомления не отправляются, а ручной повтор может создать дубли в CRM и документах. Поэтому исправление только интерфейса или ручная правка итоговой записи часто скрывает проблему, но не устраняет её.
Разбирайте события по хронологии и ищите первую точку, где фактические данные перестают соответствовать бизнес-правилу. В распределённой системе одинаково важны успешный ответ, повтор запроса, задержка события, параллельное выполнение и восстановление после временного отказа.
- Создан простой onSubmit вместо установленного trigger с нужными правами.
- Триггер таблицы ожидает namedValues, а код написан для FormResponse.
- После копирования документа trigger остался в старом проекте.
- Владелец удалён или потерял OAuth-разрешения.
- Исключение одной заявки останавливает обработку без сохранения idempotency key и повторной очереди.
Пошаговая диагностика
Создайте безопасный тестовый сценарий, максимально похожий на проблемный, но не затрагивающий реальные списания, рассылки и клиентские данные. Присвойте операции единый correlation ID и проследите его через входящий запрос, бизнес-логику, базу, очередь и внешние интеграции. Для каждого этапа фиксируйте вход, результат, код ответа, время выполнения и номер версии записи.
Сначала подтвердите сам факт расхождения, затем последовательно исключайте уровни. Сравните рабочий и ошибочный случаи по одним и тем же полям. Проверьте часовой пояс, формат идентификаторов, порядок событий, права сервисной учётной записи и актуальность конфигурации на каждом экземпляре приложения. Если результат зависит от повторного запроса, задержки или конкретного узла, это важная часть причины, а не случайный шум.
- Сопоставьте test response ID с записью execution.
- Запишите безопасные имена полей event без содержимого персональных ответов.
- Проверьте timezone проекта и timestamp строки.
- Выполните отдельную диагностическую функцию для проверки доступов используемых сервисов.
- Сравните число ответов формы, строк таблицы и успешно обработанных response ID.
Как сделать обработчик ответов надёжным
Триггер должен быть наблюдаемой точкой приёма события, а не единственным местом бизнес-логики. Ответ получает стабильный ID, проверяется, фиксируется в журнале обработки и затем передаётся идемпотентным действиям.
Надёжная реализация хранит бизнес-состояние явно и не пытается восстановить его только по экрану, случайному логу или последнему webhook. У каждого значимого действия должен быть стабильный идентификатор, понятный владелец, версия правила и проверяемый переход статуса. Повторная доставка одного события не должна создавать второе действие, а запоздавшее событие не должно возвращать объект в невозможное состояние.
- Installed trigger создан под служебным владельцем с документированными доступами.
- Adapter преобразует конкретный event object в внутреннюю схему.
- Response ID или hash используется для защиты от повторной отправки.
- Ошибки сохраняются с этапом и допускают контролируемый retry.
- Квоты, возраст необработанных ответов и сбои executions наблюдаются.
Как исправить проблему
Исправление разделите на небольшие обратимые изменения. Сначала устраните подтверждённую первопричину, затем восстановите повреждённые данные отдельной контролируемой процедурой. Не смешивайте выпуск нового кода и массовую коррекцию истории в одном непрозрачном запуске: для них нужны разные отчёты, критерии успеха и планы отката.
Если затронуты существующие записи, сначала сформируйте dry-run: список объектов, старое значение, предлагаемое новое значение и основание для изменения. Обновление должно быть идемпотентным, ограниченным точной выборкой и сопровождаться аудитом. Для финансовых данных, прав доступа и персональной информации предпочтительны компенсирующие записи, а не переписывание истории.
- Пересоздайте trigger для правильного источника и функции под устойчивой учётной записью.
- Разделите adapters формы и таблицы, не смешивая их event object.
- Повторно авторизуйте только необходимые scopes и проверьте доступ к связанным ресурсам.
- Добавьте журнал processed response IDs и идемпотентность внешних действий.
- Подготовьте функцию backfill, которая находит пропущенные ответы и сначала показывает dry-run.
Безопасный порядок внедрения
- Сохраните конфигурацию, связанные записи и необходимые журналы; отдельно проверьте, что резервную копию действительно можно восстановить.
- Воспроизведите проблему на тестовом объекте и сохраните результат до изменения, чтобы после выпуска сравнить одинаковые сценарии.
- Внесите минимальное изменение под системой контроля версий, опишите причину, ожидаемый эффект, ограничения и точный способ отката.
- Прогоните нормальный сценарий, ошибочный ввод, повтор одного запроса, два параллельных запроса и временную недоступность зависимости.
- Выпустите изменение на ограниченную долю трафика или один процесс, если архитектура это позволяет, и сравните метрики со старой версией.
- Только после стабильного наблюдения выполните контролируемое исправление исторических данных и сохраните итоговый отчёт.
Как проверить результат
Один успешный пример недостаточен. Проверьте основную операцию повторно, крайние значения, одновременные действия, перезапуск процесса и восстановление после краткого сбоя сети. Результат подтверждайте не только экраном пользователя, но и состоянием базы, очереди, внешнего сервиса и журналом аудита. Особое внимание уделите тому, что система делает при повторной доставке уже обработанного события.
Критерии приёмки сформулируйте до выпуска. Каждый пункт должен давать однозначный ответ «выполнено» или «не выполнено», а не субъективную оценку. Если тест невозможно повторить автоматически, оставьте короткий регрессионный чек-лист с тестовыми данными и ожидаемыми статусами.
- Новый тестовый ответ создаёт одну запись и одно ожидаемое внешнее действие.
- Повторная доставка того же response ID не создаёт дубль.
- Отсутствующее необязательное поле не ломает обработку всей заявки.
- Временная ошибка внешнего API сохраняется для повтора.
- Смена порядка вопросов не нарушает mapping, если используются устойчивые ключи.
Типичные ошибки при исправлении
- Проверять trigger только ручным запуском функции.
- Печатать все ответы формы в общий журнал.
- Создавать несколько одинаковых установленных триггеров.
- Использовать номер столбца без контроля заголовка или ID вопроса.
- Повторно обрабатывать все строки без идемпотентности CRM, писем и файлов.
Опаснее всего исправление, которое убирает заметный симптом ценой отключения проверки, ослабления прав или потери аудита. Такое изменение может сделать интерфейс «зелёным», но увеличить ущерб при следующем сбое. Если временный обход всё же необходим, ограничьте его срок, пользователей и область действия, добавьте мониторинг и заранее назначьте дату удаления.
Как предотвратить повторение
Профилактика строится вокруг явных контрактов, идемпотентных обработчиков, наблюдаемости и повторяемых релизов. Система должна не только корректно работать сейчас, но и быстро показывать нарушение правила после обновления, роста нагрузки или отказа интеграции. Ошибку, которая уже привела к потере времени, денег, данных или заявок, стоит закрепить автоматическим тестом.
Настройте мониторинг полного пользовательского пути, а не только доступности отдельных серверов. Техническая метрика должна быть связана с бизнес-результатом: заказ завершён, доступ выдан, файл восстановлен, событие обработано один раз, данные изолированы. Порог оповещения задавайте по нормальному профилю нагрузки и проверяйте, что уведомление содержит достаточно контекста для первого решения.
- Разница между числом новых response ID и успешно обработанных.
- Ошибки executions по функции и причине.
- Возраст самой старой необработанной заявки.
- Оставшаяся квота и частота rate limit внешних сервисов.
- Дубли CRM-записей, писем или документов по одному response ID.
Что подготовить для технического разбора
- Короткое описание ожидаемого и фактического поведения с точной последовательностью действий.
- Время возникновения, идентификатор тестового объекта и версии всех затронутых компонентов.
- Обезличенные фрагменты журналов до и после ошибки с единым correlation ID.
- Список последних изменений, результаты уже выполненных проверок и условия, при которых симптом исчезает.
- Безопасный доступ к тестовой среде либо минимальный пример, не содержащий паролей, токенов и персональных данных.
Частые вопросы
Почему ручной запуск работает, а форма нет?
Ручной запуск выполняется без event object и может иметь другой контекст; нужно смотреть установленный trigger и executions.
Можно ли восстановить пропущенные ответы?
Да, если они сохранились в форме или таблице. Backfill должен использовать стабильные ID и сначала работать в dry-run.
Кому должен принадлежать триггер?
Устойчивой управляемой учётной записи с минимальными правами и понятной процедурой передачи владения.
Когда нужна помощь специалиста
Если Apps Script пропускает ответы формы, я могу проверить trigger, владельца, event object, квоты и журналы, затем добавить идемпотентную обработку и backfill. Для оценки нужны ID проекта и источника, время тестового ответа и текст ошибки без персональных данных.