Диагностика Google Sheets в n8n: OAuth, квоты и диапазоны ¶
Обновлено: 2026-05-29
Короткий ответ ¶
Если Google Sheets в n8n создаёт дубли или обновляет не те строки, проблема почти всегда в ключе строки, range, операции append/update или пустых значениях в payload. Сначала выберите стабильный уникальный ключ: order_id, email + date, external_id или другой идентификатор из источника. Затем разделите workflow на две ветки: поиск строки по ключу и действие update или append в зависимости от результата. Для production не используйте “номер строки” как единственный ключ: он меняется после сортировки, удаления строк и ручных правок таблицы.
Быстрая развилка по симптомам ¶
| Симптом | Вероятная причина | Что проверить первым |
|---|---|---|
| Каждое событие создаёт новую строку | нет поиска по уникальному ключу | колонка external_id или order_id |
| Update меняет не ту строку | используется row number после сортировки | стабильный ключ, а не позиция строки |
| Поля становятся пустыми | payload содержит null или пустые строки |
маппинг перед update |
| n8n не видит лист | выбран не тот spreadsheet/sheet/range | spreadsheetId, gid, имя листа |
| Ошибка quota/rate limit | слишком много операций по одной строке | batching, retry, backoff |
| Даты и числа “ломаются” | таблица форматирует значения | формат колонок и режим записи |
Шаг 1. Отделите spreadsheet, sheet и range ¶
В Google Sheets легко перепутать три уровня: документ, лист внутри документа и диапазон. Документ определяется spreadsheetId из URL. Лист внутри документа имеет имя и gid. Диапазон ограничивает область чтения или записи, например Orders!A:F.
Для диагностики выпишите:
spreadsheetId: 1AbC...
sheet name: Orders
gid: 0
range: Orders!A:F
key column: order_id
Если лист переименовали вручную, старый range может перестать работать. Если в таблице есть русские названия листов, пробелы или спецсимволы, проверьте, как именно они указаны в ноде.
Шаг 2. Сделайте ключ идемпотентности ¶
Google Sheets часто используют как простую базу. Но таблица не защищает от дублей сама по себе. Если webhook пришёл два раза или workflow запустился повторно, append создаст вторую строку.
Добавьте отдельную колонку, например:
external_id | created_at | customer_email | status | amount | source
external_id должен приходить из внешней системы: ID заказа, ID платежа, ID заявки, ID сообщения. Если внешнего ID нет, соберите свой ключ, но делайте это осознанно:
={{ $json.email.toLowerCase().trim() + ':' + $json.date.slice(0,10) }}
Плохой ключ: имя клиента, номер строки, текущая дата без времени, случайный UUID при каждом запуске.
Шаг 3. Разделите append и update ¶
Безопасный upsert состоит из двух действий: сначала найти строку, потом обновить её или добавить новую. Логика:
- Google Sheets: найти строку по
external_id. - IF: строка найдена?
- Если да — update существующей строки.
- Если нет — append новой строки.
- Записать в execution результат:
createdилиupdated.
Не используйте append как универсальное действие для событий, которые могут повторяться. Для платежей, лидов, задач и CRM-синхронизации это почти гарантированно создаст дубли.
Шаг 4. Защитите данные от пустых полей ¶
Частая production-ошибка: update получает payload, где часть полей отсутствует, и затирает существующие значения пустотой. Например, CRM прислала только status, а workflow перезаписал name, phone, comment пустыми значениями.
Перед update соберите объект только из полей, которые действительно нужно менять. В Set/Edit Fields используйте явные поля, а не весь входной JSON. Для спорных значений добавьте fallback:
status: {{ $json.status || $prev.status }}
comment: {{ $json.comment ?? $prev.comment }}
Если такой fallback сложно собрать внутри одной ветки, сначала прочитайте существующую строку, затем объедините старые и новые данные в Code node.
Шаг 5. Проверьте сортировки и ручные изменения ¶
Когда команда вручную сортирует Google Sheet, номер строки перестаёт быть надёжным. Сегодня заказ находится в строке 12, завтра после сортировки — в строке 3. Если workflow хранит старый row number и делает update по нему, он может изменить чужую запись.
Для рабочих таблиц заведите правила:
- не сортировать боевой лист вручную;
- использовать отдельный view/report для менеджеров;
- хранить стабильный ID в первой колонке;
- добавлять
updated_atиsource_execution_id; - не удалять строки без архивного листа.
Если таблица уже используется вручную, лучше создать отдельный технический лист для n8n и отдельный пользовательский лист с формулами/фильтрами.
Шаг 6. Лимиты API и пакетная запись ¶
Google Sheets не любит сотни одиночных операций подряд. Если workflow обрабатывает большой массив, не обновляйте строки по одной без пауз и retry. Сначала сгруппируйте изменения, затем используйте пакетную запись, если ваша схема это позволяет.
Практичные меры:
- ограничить concurrency workflow;
- добавить retry с backoff для временных ошибок;
- не читать всю таблицу для каждого события, если достаточно поиска по ключу;
- не хранить огромные JSON в одной ячейке;
- вынести историю событий в базу, если таблица стала “почти CRM”.
Google Sheets хорош для простых операционных таблиц, но не должен становиться единственным хранилищем для высокочастотных webhook.
Контрольный тест для upsert ¶
Создайте три тестовых события:
{"external_id":"test-001","status":"new","amount":100}
{"external_id":"test-001","status":"paid","amount":100}
{"external_id":"test-002","status":"new","amount":200}
После выполнения в таблице должно быть две строки, а не три. У test-001 статус должен измениться на paid, а не появиться второй дубль.
Что не делать ¶
Не обновляйте строки по номеру, если таблицу сортируют руками. Не пишите весь входной JSON в update без фильтрации полей. Не используйте append для событий, которые могут повториться. Не храните секреты и OAuth-токены в ячейках. Не смешивайте в одном листе сырые webhook-события, рабочие статусы и отчёты для менеджеров.
FAQ ¶
Почему n8n добавляет дубли в Google Sheets?
Скорее всего, workflow всегда делает append и не проверяет уникальный ключ. Добавьте поиск строки по external_id и разделите update/append.
Можно ли использовать email как ключ?
Можно, если одна строка соответствует одному человеку. Для заказов и платежей email плохой ключ: у одного клиента может быть много событий.
Почему update затирает старые значения пустыми?
В update попадают поля, которых нет в новом payload. Перед записью соберите только разрешённые поля или объедините новое событие со старой строкой.
Почему workflow сломался после переименования листа?
Range или выбранный sheet могли ссылаться на старое имя. Проверьте sheet name, gid и spreadsheetId.
Когда пора уходить с Google Sheets на базу?
Когда нужны транзакции, высокая частота событий, строгая уникальность, история изменений и конкурентная запись. Sheets можно оставить как витрину отчётов.