Диагностика CMS — порядок проверок
Версия: 1.1 Дата: 25.04.2026 Статус: Готов к обсуждению
Документ описывает алгоритм диагностики при ошибках Decap CMS-редактора. Цель — найти корневую причину до того, как менять рабочую конфигурацию. Документ создан после ряда инцидентов, где каскадные правки конфигов усугубляли ситуацию вместо устранения.
Изменения в v1.1 (25.04.2026): добавлена секция «Ошибка: Path '<folder>' already exists» с корневой причиной (frontend-валидатор validateMetaField Decap CMS, конфликт meta.path + index_file: index с реальным index.md в папке) и проверенным решением (удаление meta: из коллекции).
Главное правило
Decap CMS-редактор (/admin/) работает только на локальном dev-сервере или локальном prod-сервере.
На production-домене (docsys.mamo.market и аналоги) папка /admin/ сознательно удаляется при деплое. Это design-решение для безопасности (CMS не должна быть публично доступна без специальной защиты).
Доказательство — tools/deploy_site.sh:
step "Удаление локальных инструментов из build/"
rm -rf "$REPO/build/admin"
ok "build/admin удалён"
Где работает CMS
| Среда | URL | Статус |
|---|---|---|
| Локальная разработка | http://localhost:3000/admin/index.html | Работает (если dev-сервер + decap-server запущены) |
| Локальный prod-просмотр | http://localhost:5000/admin/index.html | Работает (если tools/serve_preview.sh + decap-server запущены) |
| Production VPS | https://<домен>/admin/ | Не работает — admin/ удалён при деплое |
| Shared хостинг | https://<домен>/admin/ | Не работает — admin/ удалён при деплое |
Стек локального окружения
1. Docusaurus dev-сервер (порт 3000)
- Запуск:
npm startилиpm2 start ecosystem.config.js --only cms-docs-dev. - Сервирует
static/admin/config.ymlкак статику сContent-Type: text/yaml. - Сервирует MD-файлы из
docs/через MDX-loader.
2. Decap-server (целевой порт 8083, default 8081)
- Запуск:
pm2 start ecosystem.config.js --only cms-decap-server. - Прокси-сервер между Decap CMS frontend и локальным git/file-system backend.
- В
static/admin/config.ymlуказанproxy_url: http://localhost:8083/api/v1. - В
ecosystem.config.jsenvPORT: '8083'принуждает к 8083. - Decap-server читает
process.env.PORTкорректно. Default 8081 — если env не установлен.
3. cms-tools-api (порт 8084)
- Запуск через PM2.
- Внутренний API для tools-операций (генерация index.md, добавление пользователей).
Алгоритм диагностики
При ошибке CMS — проверять в этом порядке. Не пропускать шаги.
Шаг 1. URL правильный?
Открыта ли CMS по правильному URL?
- ✅
http://localhost:3000/admin/index.html— правильный URL для dev. - ✅
http://localhost:5000/admin/index.html— правильный URL для локального prod (serve_preview.sh). - ❌
http://localhost:3000/admin/— безindex.htmlDocusaurus может отдать закешированную страницу вместо CMS. - ❌
http://localhost:3000/admin#/— то же. - ❌
https://docsys.mamo.market/admin/или любой production-URL — admin/ удалён при деплое, nginx возвращает 404 HTML, Decap CMS пытается парсить HTML как YAML и падает с ошибкойYAMLSyntaxError: All collection items must start at the same column at line 1, column 1: <!DOCTYPE html>.
Если URL неправильный — открыть правильный URL и проверить ещё раз. Других проблем искать не нужно.
Шаг 2. Запущен ли Docusaurus dev-сервер на 3000?
ps aux | grep -E 'docusaurus|node.*start' | grep -v grep
curl -sI http://localhost:3000 | head -3
Ожидаемо: процесс docusaurus start или node ... start есть, curl возвращает HTTP/1.1 200 OK.
Если процесса нет — запустить:
pm2 start ecosystem.config.js --only cms-docs-dev
Шаг 3. Запущен ли decap-server на 8083?
ss -tlnp | grep ':8083'
curl -sI http://localhost:8083/api/v1 | head -3
Ожидаемо: LISTEN на 8083, curl возвращает HTTP/1.1 405 Method Not Allowed (это нормально — endpoint требует POST, не GET).
Расширенная проверка ответа:
curl -s -X POST http://localhost:8083/api/v1 \
-H "Content-Type: application/json" \
-d '{"action":"info"}'
Ожидаемый ответ:
{"repo":"cms-docs","publish_modes":["simple"],"type":"local_fs"}
Шаг 4. Свежие ошибки в логах?
tail -30 /home/alex/.pm2/logs/cms-decap-server-error.log
tail -30 /home/alex/.pm2/logs/cms-docs-dev-error.log
Типичные ошибки в логах decap-server:
Error: listen EADDRINUSE: address already in use :::8081— decap-server пытается слушать 8081 (default), но порт занят. Реальная причина в этой машине — Apache. Решение в шаге 5.Error: connect ECONNREFUSED— decap-server упал, не слушает.
Шаг 5. Decap-server crash loop с EADDRINUSE на 8081
Симптомы: в логах EADDRINUSE, decap-server рестартится много раз подряд (видно в pm2 describe cms-decap-server поле restarts:).
Причина: Apache на этой машине слушает 8081, decap-server тоже пытается на 8081 (default). Env-переменная PORT=8083 из ecosystem.config.js не подхватывается PM2 при простом restart или даже restart --update-env в PM2 v6.0.x — restart запускает процесс с уже сохранённым snapshot env.
Решение (рабочее, проверено 25.04.2026):
PM2=/home/alex/.nvm/versions/node/v24.14.1/bin/pm2
# 1. Проверить, кто занял 8081
ss -tlnp | grep ':8081' # часто Apache
# 2. Полностью удалить процесс — НЕ просто restart
$PM2 delete cms-decap-server
# 3. Стартовать заново через ecosystem.config.js
cd /home/alex/sites/cms-docs
$PM2 start ecosystem.config.js --only cms-decap-server
# 4. Сохранить pm2 dump (чтобы переживало reboot)
$PM2 save
# 5. Проверить
ss -tlnp | grep ':8083'
curl -X POST http://localhost:8083/api/v1 \
-H "Content-Type: application/json" \
-d '{"action":"info"}'
Ожидаемое: LISTEN на 8083, curl отдаёт корректный JSON.
Почему pm2 restart --update-env не работает: в PM2 v6.0.x команда restart запускает процесс с уже сохранённым snapshot env, в котором PORT отсутствует. Только delete + новый start ecosystem.config.js создаёт fresh process с правильной env.
Путь к PM2 в этом окружении: pm2 не в PATH; полный путь /home/alex/.nvm/versions/node/v24.14.1/bin/pm2.
Шаг 6. CMS Config Errors про buttons
Симптомы: в браузерной консоли ошибка про неподдерживаемое значение в editor_components → buttons.
Причина: обновление Decap CMS изменило список allowed values для buttons.
Решение: см. Руководство по установке → раздел проблем после обновления Decap CMS.
Шаг 7. Только если все шаги выше пройдены — смотреть в документы
Только если все 6 шагов выше дали зелёный — проблема может быть в самих документах. Проверить:
- Frontmatter валиден (YAML парсится, парные
---, кодировка UTF-8). - Frontmatter содержит
draft: false(Decap CMS schema требует). - Schema-совместим с
cms-config.jsonи_project_.json. - MDX-safe (нет голых
<digitв plain-тексте). - Кодировка UTF-8 без BOM.
- Между H1 и шапкой документа — пустая строка.
Подробности — в Правила оформления документов.
Типичные ошибки и их корневые причины
Ошибка: Failed to load entry: TypeError: Failed to fetch + YAMLSyntaxError: All collection items must start at the same column at line 1, column 1: <!DOCTYPE html>
Причина: CMS открыта на production-URL или на dev-URL без index.html. Сервер возвращает HTML (404 или закешированную страницу), Decap CMS пытается парсить HTML как YAML.
Решение: Открывать CMS только по локальному URL с index.html в конце пути:
http://localhost:3000/admin/index.html(dev);http://localhost:5000/admin/index.html(prod черезserve_preview.sh).
Что НЕ является причиной:
- Формат документов;
- Frontmatter;
- YAML в
config.yml(он валиден).
Не нужно править документы или конфиги, чтобы устранить эту ошибку. Достаточно сменить URL.
Ошибка: EADDRINUSE в логах decap-server, CMS не работает локально
См. шаг 5 алгоритма выше.
Ошибка: Failed to fetch без YAML-ошибки
Причина: decap-server не запущен или не слушает на 8083.
Решение: см. шаг 3 алгоритма выше.
Ошибка: Path '<folder>' already exists при Publish существующего документа
Симптом: при попытке Publish или Save существующего документа CMS показывает ошибку вида Path 'project-slug/folder' already exists и блокирует сохранение. В логах decap-server при этом нет новых записей — запрос даже не уходит на backend, ошибка генерируется во frontend-валидации Decap CMS.
Корневая причина: в коллекции одновременно используются три параметра — nested, meta.path и index_file: index — а в папке проекта рядом с обычными документами лежит index.md. Frontend-валидатор Decap CMS (validateMetaField в decap-cms-core/src/actions/entries.ts) собирает кандидат-путь как <folder>/<meta.path>/index.md, находит реальный index.md соседом редактируемого документа и считает это коллизией путей.
Подтверждение в исходниках Decap CMS v3:
-
Текст ошибки в
decap-cms-locales/src/en/index.js:pathExists: "Path '%{path}' already exists" -
Логика валидации:
decap-cms-core/src/actions/entries.ts(функцияvalidateMetaField):if (existingEntryPath && existingEntryPath !== draftPath) {return getPathError(value, 'pathExists', t);} -
Резолв кандидат-пути:
decap-cms-core/src/reducers/entryDraft.js(функцияselectCustomPath) собирает значениеcustomPath:customPath = join(collection.folder, meta.path, `${index_file}.${extension}`) -
Гейт срабатывания:
decap-cms-core/src/reducers/collections.ts(функцияselectHasMetaPath) — проверка только на наличиеmeta.path, параметрnestedтут роли не играет.
Известный baseline-issue в апстриме:
- decaporg/decap-cms#4317 — Path Meta Field Is Required. Симптом совпадает: «existing pages show prepopulated values that trigger duplicate path errors upon save». Открыт, без фикса в апстриме.
Решение (минимально инвазивное, проверено 25.04.2026):
В static/admin/config.yml коллекции docs удалить строку meta: целиком:
collections:
- name: docs
folder: docs
create: true
nested:
depth: 10
slug: "{{slug}}"
extension: md
format: frontmatter
# meta: { path: { widget: string, label: Path, index_file: index } } ← удалено
fields:
- { label: Заголовок, name: title, widget: string }
- { label: Черновик, name: draft, widget: boolean, default: false, required: false }
- { label: Содержимое, name: body, widget: markdown }
Поле meta.path — опциональное. По официальной документации Decap оно нужно только для возможности перемещать документы между папками через CMS-редактор. Для штатной правки тела документа оно не требуется.
После правки config.yml:
- Сохранить файл (
tools/build_auth.shи Docusaurus dev-сервер не требуют перезапуска —config.ymlотдаётся как статика). - В браузере на странице CMS — Ctrl+Shift+R (хард-релоад), чтобы браузер взял новый
config.yml. - Проверить — Publish существующего документа должен пройти.
Что сохраняется и что теряется:
- ✅ Сохраняется:
nested: depth: 10(навигация по дереву папок), открытие документов, чтение, сохранение в исходное имя файла. - ✅ Сохраняется:
index.mdкак специальный файл-страница папки в Docusaurus. - ❌ Теряется: возможность перемещать документ между папками через поле Path в CMS-редакторе. Перенос — только через файловый менеджер или git mv.
Если нужна возможность перемещения через CMS:
Единственный обходной путь, известный в апстриме — разнести index.md-файлы и обычные документы по разным коллекциям: одна nested коллекция для индексов, отдельная folder-коллекция для leaf-документов. Это существенное изменение архитектуры, эскалируется владельцу системы.
Что НЕ является причиной этой ошибки:
- Формат документа, frontmatter, MDX-парсер.
- Кэш браузера или Service Worker.
- Состояние decap-server (8083) — запрос до него не доходит.
- Версия Decap CMS (3.x) — это поведение присутствует во всех релизах после введения
meta.path.
Ошибка: вход в CMS не работает (логин/пароль не принимается)
Причина: CREDENTIALS_HASH в static/admin/index.html не соответствует паролю в cms-config.json.
Решение: обновить пароль через tools/add_user.sh --admin <newpassword>. Скрипт атомарно обновит и cms-config.json, и static/admin/index.html.
Запрещено редактировать CREDENTIALS_HASH руками.
Путь развёртывания CMS на production (если бизнес-требование)
Если CMS на production действительно нужна:
- Закомментировать
rm -rf "$REPO/build/admin"вtools/deploy_site.sh. - Защитить
/admin/через nginx basic auth, client cert, или OAuth-прокси. - Реализовать proxy для
/admin/api/v1/*к decap-server (или git-gateway backend). - Передеплоить.
Это противоречит изначальному design-решению. Эскалируется к автору cms-docs системы.
Связанная документация
- Стандарт работы с системой документации — единый свод правил, потоки работы, стек локального окружения.
- Руководство по установке — установка и проблемы Decap CMS.
- Деплой на VPS — Docker + Traefik — деплой в production.
- Чек-лист — создавать так чтобы сразу работало — обязательные проверки до и после правки.
- Правила оформления документов — frontmatter, шапка, MDX-safe.