Перейти к содержимому
Забрать бесплатно
Модификации выключены. Так эта страница выглядит на обычной Тильде.

Ошибки 402, 403 и 429 на Тильде: один код ответа, пять разных реакций

29 июля 2026 12 МИН КОМАНДА MODKOD

Если на сайте на Тильде что-то не загрузилось и в консоли появилось число в квадратных скобках — это HTTP-статус ответа. Я прочитал все 53 файла рантайма Тильды и замерил в браузере, что её код делает при каждом коде ответа. Оказалось, что единого правила нет: у Тильды пять разных слоёв запросов, и один и тот же 403 в них даёт от одного до пяти обращений к серверу. Номера 402 и 403 при этом не названы в коде ни разу.

✓ ПРОВЕРЕНО 29 июля 2026 отсутствие номеров 401, 402, 403, 409 и 503 в контексте статуса во всех 53 файлах рантайма; единственные два вхождения 404 — внутри jQuery, без ветки Тильды; условие повтора (>=500, 408, 410, 429, таймаут) ровно в трёх файлах и три разных способа распознать таймаут; самоограничение переключения сравнением строки, а не счётчиком; браузерный замер t_loadJsFile на статусах 402, 403, 429, 500 и 200 с задержками повторов; браузерный замер t_store_changeEndpoint и changeEndpoint доставки на девяти статусах и таймауте; браузерный замер t_store__fetchApiData с подсчётом хостов; три формы сообщения об ошибке и случай, когда номер статуса из сообщения исчезает; мёртвая переменная o=3 в t_loadJsFile и t_loadCSSFile — 53 файла рантайма Тильды и замеры в chromium через playwright

Короткий ответ

В 53 файлах рантайма Тильды номера 402 и 403 не названы ни разу. Повторяет запрос она по списку: 500 и выше, 408, 410, 429 и таймаут. Но это только один из слоёв: загрузчик файлов повторяет пять раз при любом отказе, а новый слой магазина на fetch — при любом ответе вне 200–299, включая 403.

Что именно я мерил, и чего этот замер не знает

Мерил две вещи. Первая — 53 файла рантайма Тильды: искал каждое место, где код смотрит на статус ответа. Вторая — поведение в браузере: брал её же функции без правок, подсовывал им сервер, который отдаёт нужный код, и считал запросы.

Чего здесь нет и быть не может: это код, работающий в браузере. Он не знает и не может сказать, почему сервер Тильды ответил 402 или 403 именно на вашем сайте. Если вы пришли за этим — ответ у поддержки Тильды, а не в коде страницы. Здесь другое: что происходит после такого ответа, и как по тексту в консоли понять, какая именно служба не ответила.

Число в квадратных скобках — это HTTP-статус

Первое, что стоит знать: если вы видите [403] или [429], это не внутренний код Тильды. Это статус ответа, вставленный в строку:

// каталог, tilda-catalog-1.1
o = t && t.responseText > "" ? "[" + t.status + "] " + t.responseText
  : t && t.statusText   ? "Error [" + t.status + ", " + t.statusText + "]"
  : "Error type [" + t.type + "]";
console.error(o + ". Please, try again later.");

Форма сообщения зависит от того, что пришло от сервера. Замерил все три случая, вызывая эту функцию Тильды с разными ответами:

Что ответил серверЧто напечатано
403 и тело Forbidden[403] Forbidden. Please, try again later.
403, тела нет, есть statusTextError [403, Forbidden]. Please, try again later.
403, ни тела, ни statusTextError type [undefined]. Please, try again later.

Третья строка — ловушка: номер статуса из сообщения исчезает совсем. Пустой ответ с кодом 403 даёт текст, по которому нельзя понять, что это был 403. У доставки та же развилка, но с четвёртой веткой, и там номер остаётся: [403] Unknown error. Please, try again later.

Пять слоёв запросов, и в каждом свой список поводов

Это главное. У Тильды не одно правило повтора, а пять, и они не согласованы между собой. Таблица собрана из замеров: колонки «403» и «429» — сколько обращений к серверу я насчитал.

СлойГде живётЧто считает поводом повторить403429
Загрузка js и csstilda-scripts-3.0любой отказ; статус коду не виден5 запросов5 запросов
Магазин на fetchtilda-cart-1.1, tilda-delivery-1.0любой ответ вне 200–2992 запроса2 запроса
Каталог на XHRtilda-catalog-1.1≥500, 408, 410, 429, таймаутне повторяетвызывает повтор
Доставкаtilda-delivery-1.0≥500, 408, 410, 429, таймаутне повторяетвызывает повтор
Формыtilda-forms-1.0≥500, 408, 410, 429, таймаутне повторяетотправляет заново

Разница между 403 и 429 живёт только в трёх нижних строках. В двух верхних код ответа не важен вообще.

Загрузчик файлов: пять запросов при любом статусе

Когда Тильда догружает свой js или css, она делает это через t_loadJsFile. Повтор там висит на событии error у тега <script>, а это событие не несёт HTTP-статуса — браузер его не отдаёт. Поэтому 402, 403, 429 и 500 для загрузчика неразличимы:

function t_loadJsFile(t, e, n) {
  void 0 === n && (n = 0);
  var o = 3, i = 1e3, r = t_modifyRootZone(t);
  // …
  a.addEventListener("error", function (t) {
    if (!(n <= 3)) {
      var o = t.message || "<no error message>";
      throw new Error("Failed to load " + r + " script: " + o, { cause: t })
    }
    setTimeout(function () {
      a.remove(), t_loadJsFile(r, e, n + 1),
      console.warn("Retrying to load " + r + ". Retry: " + (n + 1))
    }, n * i)
  })
}

Замер: поднял страницу, подсунул адрес, который всегда отдаёт нужный код, и посчитал обращения.

Сервер отдаётЗапросовКогда, мс от первого
40350, 4, 1008, 3011, 6014
40250, 2, 1005, 3007, 6010
42950, 3, 1007, 3012, 6015
50050, 2, 1005, 3007, 6009
200 (контроль)10

Три вещи, которые видно в этих числах и в коде.

Первый повтор уходит мгновенно. Задержка считается как n * i, где i — 1000 мс, а n на первом отказе равно нулю. Ноль умножить на тысячу — ноль. Дальше 1000, 2000 и 3000 мс, и все пять запросов укладываются в шесть секунд.

Повторов четыре, а не три. Условие n <= 3 истинно при n равном 0, 1, 2 и 3, то есть повтор назначается четыре раза, и запросов получается пять. После пятого отказа код бросает исключение.

Переменная o = 3 не читается. Она объявлена рядом с задержкой и, судя по значению, задумывалась как предел числа попыток. Но в самом сравнении стоит литерал 3, а внутри обработчика o переопределяется под текст ошибки. Ровно то же самое — в t_loadCSSFile, слово в слово, включая мёртвую o.

Новый слой магазина: повтор при любом ответе вне 200–299

Часть запросов каталога и корзины идёт уже не через XMLHttpRequest, а через fetch. Здесь решает одна строка:

Promise.resolve(fetch(t, s)).then(function (t) {
  if (clearTimeout(m), !t.ok) throw new Error("HTTP error! Status: " + t.status);
  return Promise.resolve(parseResponse(t, _))
})

response.ok ложно для любого статуса вне 200–299. Значит 402 и 403 здесь бросают исключение так же, как 500, а обёртка выше ловит его и уходит на дублёра — не разбирая, что именно случилось:

_catch$a(
  function () { return fetchWithRedirectHandling(t_cart__getStoreEndpointUrl(e, r), n) },
  function (t) {
    console.error("Initial fetch failed, retrying with fallback URL:", t);
    return fetchWithRedirectHandling(t_cart__getStore2EndpointUrl(e, r), n)
  }
)

Замер на странице с data-tilda-root-zone="ru", подсчёт по хостам:

Сервер отдаётЗапросовКуда
4032store.tildaapi.ru, затем store2.tildaapi.ru
4022то же
4292то же
5002то же
200 (контроль)1только store.tildaapi.ru

То есть на вопрос «повторяет ли Тильда запрос при 403» правильный ответ — «в этом слое да, ровно один раз». Таймаут по умолчанию здесь 30 секунд, а у запроса товаров по идентификатору — 20.

Старый слой на XHR: список кодов, и 402 с 403 в него не входят

Три файла содержат одну и ту же конструкцию. Вот версия каталога:

function t_store_changeEndpoint(t, e) {
  if (t && (t.status >= 500 || 408 == t.status || 410 == t.status
      || 429 == t.status || "timeout" === t.type)
      && -1 !== window.t_store_endpoint.indexOf("store.tilda")) {
    var r = t_store__getRootZone();
    window.t_store_endpoint = "store2.tildaapi." + r;
    "function" == typeof e && e()
  } else { /* печать в консоль */ }
}

Замер: вызывал эту функцию Тильды с поддельным ответом на каждом статусе. Контроль — 429 обязан переключить адрес, 200 обязан не переключать.

СтатусАдрес послеПовтор
200 (контроль)store.tildaapi.ruнет
402store.tildaapi.ruнет
403store.tildaapi.ruнет
404store.tildaapi.ruнет
408store2.tildaapi.ruда
410store2.tildaapi.ruда
429store2.tildaapi.ruда
500store2.tildaapi.ruда
503store2.tildaapi.ruда
таймаутstore2.tildaapi.ruда

Обратите внимание: 503 переключает, хотя в списке его нет. Он проходит по условию status >= 500. А 402, 403 и 404 не проходят ни по одному из пяти условий и уходят в общую ветку с печатью в консоль.

Повтор ровно один, и это сделано не счётчиком

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

СлойСторожАдрес после переключенияСторож после
КаталогindexOf("store.tilda")store2.tildaapi.<зона>не находит подстроку
ФормыindexOf("forms.tilda")forms2.tildacdn.comне находит подстроку
Доставка".tildacdn.com" === endpointDelivery2.tildacdn.comравенство ложно

После первого переключения условие становится ложным навсегда — до перезагрузки страницы. Даже если сервер продолжает отвечать 429, третьего адреса не будет.

Ещё одна деталь той же семьи: таймаут в этих трёх файлах распознаётся тремя разными способами — "timeout" === t.type в каталоге, t.isTimeout в доставке и "timeout" == xhr.statusText в формах.

И одна разница, которая важнее, чем кажется: каталог при переключении зону перечитывает, поэтому дублёр получается store2.tildaapi.ru. А формы уходят на зашитый forms2.tildacdn.com — то есть сайт в зоне .ru при отказе форм отправляет данные на .com.

402, 403 и остальные номера, которых в коде нет

Проверил каждый номер отдельно: искал его в тексте всех 53 файлов и оставлял только те вхождения, рядом с которыми есть status, statusText, type или readyState.

НомерВхождений в контексте статуса
4010
4020
4030
4042, оба внутри jQuery
4090
4293, по одному в формах, каталоге и доставке
5030, но проходит по >= 500

Две находки 404 — это внутренности jQuery (status = responses.text ? 200 : 404, обход старой ошибки в IE). Своей ветки на 404 у Тильды нет ни одной.

Как по тексту понять, какая служба не ответила

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

Что видноКакой слойГде смотреть
Retrying to load … Retry: 1не загрузился файл js или cssконсоль, warn
Failed to load … script:тот же файл, все пять попыток исчерпаныконсоль, необработанное исключение
Fetch error: Error: HTTP error! Status: 403новый слой магазинаконсоль
Initial fetch failed, retrying with fallback URL:тот же слой, уходит на дублёраконсоль
Error type [undefined]. Please, try again later.каталог, и ответ пришёл пустымконсоль
[403] Unknown error. Please, try again later.доставкаконсоль
[403] … в блоке ошибки под формойформысама страница

Последняя строка — единственная, которую видит обычный посетитель. Ошибки каталога и доставки уходят только в console.error: человек видит пустой список товаров или не открывшийся расчёт доставки, и никакого сообщения.

Отдельный случай — обрыв связи, а не код ответа. Формы проверяют его так:

if (!secondFormTypeXhr || 0 == secondFormTypeXhr.status && tsDelta < 100)
  allError.forEach(function (t) {
    t.innerHTML = "Request error (sending form data). Please check internet connection..."
  })

Статус 0 и меньше 100 мс с начала отправки — значит запрос не ушёл. Этот текст про интернет не имеет отношения ни к 402, ни к 403.

Как проверить у себя

  1. Откройте страницу, где что-то не работает, с открытой консолью.
  2. Найдите в консоли строку с числом в квадратных скобках или со словом Retrying. По таблице выше определите слой.
  3. Перейдите на вкладку «Сеть», включите фильтр по tilda, перезагрузите страницу. Красные строки покажут и адрес, и настоящий код ответа — тот самый, который стоит в скобках.
  4. Если запросов к одному адресу пять с интервалами примерно 0, 1, 2 и 3 секунды — это загрузчик файлов. Если два, ко второму адресу с цифрой 2 в имени, — это переключение на дублёра.

Чего сделать нельзя: заставить код повторить запрос при 403. Список поводов зашит в минифицированный файл на стороне Тильды.

Что из этого следует

Одна общая мысль: в рантайме Тильды нет единого обработчика ошибок. Есть пять независимых слоёв, написанных в разное время, и они расходятся даже в мелочах — в способе распознать таймаут, в том, теряется ли зона при переключении, и в том, останется ли номер статуса в тексте сообщения.

Для практики это значит, что диагностировать нужно от слоя, а не от номера ошибки. Один и тот же 403 в одном месте вызовет пять запросов за шесть секунд, в другом — два, а в третьем тихо напечатает строчку в консоль, которую никто не прочитает.

Куда смотреть дальше: адреса всех служб и то, как они собираются из зоны, разобраны в «static.tildacdn.com». Какие файлы рантайма догружаются по требованию и почему их не видно в списке загрузок — в «переносе сайта с Тильды». Если нужно, чтобы ошибка не оставалась только в консоли, а показывалась посетителю, — это уже работа с бэкендом.

Вопросы по этой статье 5

403 — это ответ сервера «доступ запрещён». Сам код Тильды, который работает в браузере, этот номер нигде не разбирает: во всех 53 файлах рантайма номера 403 нет ни в одной проверке статуса. Он попадает в общую ветку «не получилось» и печатается в консоль как есть. Почему сервер ответил именно так, из кода страницы узнать нельзя — это вопрос к поддержке Тильды.