Gathio 1.6.7 排错FAQ

Gathio 1.6.7(Docker Compose + MongoDB 7.0)部署运行中的 17 个高频故障问答:配置缺失崩溃循环、TOML 语法错、GATHIO_ 变量未设、端口占用、Mongo 不可达假在线、进程崩溃重启、自毁时区、邮件 none 行为、评论字段错、ICS 导入 500、editToken 403 与找回、联邦 https 硬要求等,全部为实测复现与处置。

GathioGathioNodejsMongoDBDocker2026/11/02

Gathio 1.6.7 排错FAQ

目标:汇集 Gathio 1.6.7 在 Docker Compose 部署(应用 + MongoDB 7.0,宿主端口 8153)环境实测复现的故障场景与处置方法。每个问题给出真实报错回显、根因与验证步骤;部署与配置基线见 《Gathio 1.6.7 Docker Compose 部署指南》,功能面与架构见 《Gathio 1.6.7 介绍与选型指南》。

一、环境信息

  • 操作系统:Ubuntu 24.04.5 LTS;Docker 29.9.2(build a82e528)、Docker Compose v5.6.1
  • 应用:ghcr.io/lowercasename/gathio:1.6.7(容器名 gathio-app,Node.js v22.23.3,宿主 8153→容器 3000)
  • 数据库:mongo:7.0(容器名 gathio-db,服务端 v7.0.45,仅容器网络内可达)
  • 配置:/opt/gathio/config/config.toml(bind mount 到 /app/config)
  • 本文所有报错均为在测试栈上人为注入故障后抓取的真实回显

二、故障速查表

症状最可能原因问题编号
容器反复 Restarting、HTTP 连接拒绝config.toml 缺失Q1
容器反复 Restarting、日志有 SyntaxErrorTOML 语法错误Q2
容器反复 Restarting、日志有 MongoParseError${GATHIO_...} 变量未设置Q3
up 时报 port is already allocated宿主端口被占Q4
首页 200 但活动页 404 且响应约 10 秒MongoDB 不可达(假在线)Q5
容器无故重启、Up 秒数很小DB 超时未捕获崩溃Q6
活动数据丢失需 mongorestore 恢复Q7
活动到期后自动消失自毁调度(UTC 时区)Q8
/events 404show_public_event_list=falseQ9
收不到任何邮件 / 群组订阅 500mail_service=noneQ10
评论提交成功但不显示表单字段名错误Q11
ICS 导入 500multipart mimetype 不对Q12
编辑/删除活动 403editToken 错误Q13
编辑令牌 URL 丢失DB 查询或 magic link 找回Q14
实例描述改了不生效文件名缺 locale 后缀Q15
Mastodon 关注失败domain 非公网 HTTPSQ16
健康检查端点 404无 /healthz,属设计Q17

三、启动与配置类

Q1:容器状态 Restarting (1),curl 返回 000,日志只见 npm 横幅

故障注入:移走 config.toml 后 docker compose restart gathio。实测回显:

docker logs gathio-app | tail -4
> gathio@1.6.7 start
> node dist/start.js

[31mConfiguration file not found! Have you renamed './config/config.example.toml' to './config/config.toml'?

docker ps -a --format '{{.Names}} {{.Status}}' | grep '^gathio-app'
gathio-app Restarting (1) Less than a second ago

curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8153/
HTTP 000

根因:Gathio 启动第一步读 /app/config/config.toml,文件不存在直接退出;restart: unless-stopped 使其循环重启([31m 为 ANSI 红色转义,说明该行是醒目报错)。处置:从镜像提取示例生成配置并改 domain/mongodb_url:

docker run --rm ghcr.io/lowercasename/gathio:1.6.7 cat /app/config/config.example.toml > /opt/gathio/config/config.toml
docker compose up -d --force-recreate gathio
curl -s -o /dev/null -w "RESTORED HTTP %{http_code}\n" http://localhost:8153/
RESTORED HTTP 200

Q2:日志报 Error parsing configuration

故障注入:在 config.toml 末尾追加一行无等号的文本。实测回显:

Error parsing configuration: [SyntaxError: Expected "=" or [ \t] but "l" found.]

根因:TOML 解析失败(真实报错对象还带 line/column/offset 定位字段,实测例:line:4, column:6)。处置:按定位修正;常见诱因是复制粘贴引入全角字符/不可见字符、键值写错段(如 mongodb_url 落到 [general])。改完 docker compose restart gathio 用 docker logs 验证。

Q3:日志 MongoParseError: Invalid connection string,RestartCount 持续上涨

故障注入:配置写 mongodb_url = "${GATHIO_MONGODB_URL}" 但未在 compose 设置该环境变量。实测回显:

Config references environment variable "GATHIO_MONGODB_URL" which is not set. The literal string "${GATHIO_MONGODB_URL}" will be used instead.
Connection error: Invalid connection string
MongoParseError: Invalid connection string
    at parseConnectionString (/app/node_modules/.pnpm/mongodb@3.7.4/node_modules/mongodb/lib/core/uri_parser.js:585:21)

docker inspect gathio-app --format 'RestartCount={{.RestartCount}}'
RestartCount=4

根因:${GATHIO_名字} 替换仅对已设置的 GATHIO_ 前缀变量生效;未设置时官方文档称「保留字面量」,实测后果更严重——字面量被当作连接串,驱动解析失败进程直接崩溃并循环重启。处置:在 compose environment: 补齐对应变量,或配置里直接写实际 URL。

Q4:up 报 Bind for 0.0.0.0:8153 failed: port is already allocated

故障注入:临时容器占住 8153 后启动应用。实测回显:

Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint gathio-app (89433a7a81d12e9313c6dca1849b56a799e527e646e5db0fb5823c362c372742): Bind for 0.0.0.0:8153 failed: port is already allocated

定位:ss -lntp | grep 8153 查占用者。处置:停掉占用服务;或改 compose ports: 宿主侧端口,并同步修改 config.toml 的 domain(域名含端口时两者必须一致,否则生成的活动链接/联邦对象端口错误)。

四、数据库与数据类

Q5:首页 200,但活动页 404 且响应耗时约 10 秒

故障注入:mongodb_url 改为 mongodb://db.invalid:27017/gathio。实测回显:

curl -s -o /dev/null -w "GET / -> HTTP %{http_code} (%{time_total}s)\n" http://localhost:8153/
GET / -> HTTP 200 (0.107381s)

curl -s -o /dev/null -w "GET /_0nu7QEITrI8SXhvQhEzc -> HTTP %{http_code} (%{time_total}s)\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET /_0nu7QEITrI8SXhvQhEzc -> HTTP 404 (10.007787s)

docker logs gathio-app --since 60s | grep -m2 "buffering timed out"
Error saving log entry! MongooseError: Operation `logs.insertOne()` buffering timed out after 10000ms
MongooseError: Operation `events.findOne()` buffering timed out after 10000ms

根因:Gathio 启动不强制校验数据库连接——HTTP 服务照常起(首页是静态渲染),但 Mongoose 操作缓冲 10 秒后超时,页面查询失败被当作「活动不存在」返回 404。「响应恰好慢 10 秒」是数据库不可达的最强信号。处置:

docker exec gathio-app nc -zv mongo 27017
mongo (172.24.0.2:27017) open

不通则检查 compose links:、网络与 mongodb_url 主机名;恢复后 docker compose up -d --force-recreate gathio。

Q6:容器自己重启了,docker ps 显示 Up 几十秒,日志末尾是 Node 崩溃栈

根因:部分代码路径对 DB 超时没有捕获(实测:公开活动列表页的 countDocuments 超时直接抛出未捕获异常,Node.js v22.23.3 进程退出),restart: unless-stopped 随即拉起,表现为「Up 20 seconds」现象。处置:按 Q5 恢复数据库连通即可根治;不要靠重启掩盖问题。

Q7:活动数据丢了,如何用备份恢复

Gathio 无单活动回收站,删除/误清只能靠 mongodump 备份恢复。实测完整链路(备份文件 9249B):

docker exec gathio-db mongosh --quiet gathio --eval 'printjson(db.events.deleteMany({}))'
{ acknowledged: true, deletedCount: 2 }

curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
HTTP 404

docker cp ./gathio-backup.tar gathio-db:/tmp/gathio-backup.tar
docker exec gathio-db mongorestore --db gathio --drop --archive=/tmp/gathio-backup.tar --gzip 2>&1 | tail -1
2026-11-01T15:50:23.048+0000	11 document(s) restored successfully. 0 document(s) failed to restore.

curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
HTTP 200

⚠️ 注意:--drop 会先删同名集合再恢复,回滚的是整个库(含 logs/eventgroups);封面图文件在 /opt/gathio/images,需与 mongodump 同批备份,只恢复 DB 不恢复图片目录会导致活动页图片 404。

五、功能行为类

Q8:活动到期后自己消失了,是不是 bug

是设计行为(隐私优先的自毁机制)。实测源码 /app/dist/routes.js:23:schedule.scheduleJob 注册 cron 59 23 * * *,每天 23:59 删除 end <= now - delete_after_days 的活动与图片文件(审计 process=deleteOldEvents)。两个易错点:① 调度按容器本地时区执行,官方镜像默认 UTC,与北京时间差 8 小时;② delete_after_days = 0 才关闭自毁,默认 7。需要长期留存的活动数据请提前导出 ICS 或 mongodump。

Q9:GET /events 返回 404

实测:show_public_event_list = false(默认)时 GET /events → 301 → /events/ → 404。这是开关行为不是故障;改 true 后 /events 公开活动列表成为首页。

Q10:主办收不到活动创建邮件;RSVP 没发信;群组订阅报 500

根因:mail_service = "none"(默认)。实测行为链:启动日志固定警告 "You have not configured this Gathio instance to send emails!";RSVP 邮件只打印控制台(Sending emails to: zhangsan@example.com);POST /magic-link/event/create 返回 200 但不发信;群组订阅 POST /subscribe/:groupID 直接 500。处置:生产配置 [general] mail_service = "nodemailer" + [nodemailer] 段 SMTP 参数(密码用 ${GATHIO_SMTP_PASSWORD} 注入),或 sendgrid/mailgun 通道。

Q11:评论 POST 返回 200/302,页面上却没有评论

根因:字段名错误。正确字段是 commentContent/commentAuthor;实测用 comment/commentName 提交,HTTP 不报错,但 Mongoose ValidationError 只记入 logs 集合、评论不入库:

curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:8153/post/comment/_0nu7QEITrI8SXhvQhEzc \
  --data-urlencode "comment=hello?" --data-urlencode "commentName=Wang"
HTTP 200

docker exec gathio-db mongosh --quiet gathio --eval 'printjson(db.logs.find({status:"error"},{_id:0,process:1,message:1}).sort({timestamp:-1}).limit(1).toArray())'
[
  {
    process: 'addEventComment',
    message: 'Attempt to add comment to event _0nu7QEITrI8SXhvQhEzc failed with error: ValidationError: comments.1.author: Path `author` is required., comments.1.content: Path `content` is required.'
  }
]

正确字段实测:curl -s -i -X POST http://localhost:8153/post/comment/_0nu7QEITrI8SXhvQhEzc --data-urlencode "commentContent=Can I bring a friend?" --data-urlencode "commentAuthor=Lisi" → HTTP/1.1 302 Found,mongosh 查 db.events.findOne({name:"Test2"}).comments 可见 { author: 'Lisi', content: 'Can I bring a friend?' }(错误字段提交后该数组不变)。

Q12:ICS 导入报 500,堆栈 Only ICS files are allowed.

根因:POST /import/event 的 multipart 文件字段 icsImportControl 的 mimetype 必须是 text/calendar(curl -F 默认 application/octet-stream 会被 multer fileFilter 拒绝,且该错误未走 400 而是 500)。处置:显式指定类型,实测成功:

curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:8153/import/event -F "icsImportControl=@import.ics;type=text/calendar"
HTTP 200

随后 db.events.findOne({name:"Imported From ICS"}) 的实测输出含 { id: 'quuqOXXj7FB6LrjPEnjiR', name: 'Imported From ICS' }。

Q13:编辑/删除活动返回 403

根因:editToken 不对。实测 PUT /event/:id 携带错误 editToken → 403 Forbidden 且内容不变;携带正确令牌 → 200、字段更新(logs 记 editEvent success)。URL 形态:/<eventID>?e=<32位令牌>。注意删除接口是路径式 POST /deleteevent/:eventID/:editToken(实测 302 回首页、DB 文档消失)。

Q14:主办把带 ?e= 的管理链接弄丢了,还能找回吗

能,两条实测路径:

  1. 数据库直查(有宿主权限时最快):editToken 明文存在活动文档里:
docker exec gathio-db mongosh --quiet gathio --eval 'printjson(db.events.find({},{_id:0,id:1,name:1,editToken:1,creatorEmail:1}).toArray())'
[
  { id: '_0nu7QEITrI8SXhvQhEzc', name: 'Test2', creatorEmail: 'admin@example.com', editToken: 'huzcvsxcofg3tjy6aq9138rw6wg70efq' },
  { id: 'quuqOXXj7FB6LrjPEnjiR', name: 'Imported From ICS', editToken: 'f9fceq4woiu4o5sfwuopmna2n7yfmj8d' },
  { id: 'cWI7ePnEPxs4JEK45qvbN', name: 'Team Retro', creatorEmail: 'admin@example.com', editToken: '3a20dzqt3hrxgrudl1qp0nm2tf0z4lqu' }
]

拼回 https://<domain>/<id>?e=<editToken> 即恢复管理入口。

  1. magic link:POST /magic-link/event/create(字段 creatorEmail)向主办邮箱发编辑链接——前提是已配置邮件通道(Q10),mail_service=none 时返回 200 但永远收不到信。

Q15:改了 static/instance-description.md 首页描述没变化

实测坑点:实例描述文件必须带 locale 后缀——instance-description.md 不生效,instance-description-en.md 才生效(界面语言 locales 仅 de/en/ja/nn/pt,无中文)。文件支持 {{ siteName }} 模板串;改后 docker compose restart gathio 验证首页文案变化。未提供该文件时回落默认文案 "Gathio is running on Gathio — a simple, federated, privacy-first event hosting platform."。

Q16:Mastodon 搜不到/关注失败活动账号

根因:domain 配置问题。实测本机 domain = "localhost:8153" 时,nodeinfo/webfinger 返回的 href 一律是 https://localhost:8153/.well-known/nodeinfo/2.2 形态(https 前缀硬编码):

curl -s http://localhost:8153/.well-known/nodeinfo
{"links":[{"rel":"http://nodeinfo.diaspora.software/ns/schema/2.2","href":"https://localhost:8153/.well-known/nodeinfo/2.2"}]}

Gathio 自身不终结 TLS,联邦对象 URL 固定按 https://<domain> 生成——本地/内网 HTTP 部署时外部实例回访必然失败。处置:domain 配公网 HTTPS 域名 + Nginx/Caddy 反代(证书在反代终结),并确认 is_federated = true;改完重启后可用 curl https://<domain>/.well-known/webfinger?resource=acct:<eventID>@<domain> 验证返回 self link。

Q17:健康检查端点 /healthz 404,是不是没装好

是设计如此:实测 GET /healthz → 404,Gathio 无专用健康路由。监控方案:① 存活探测用 GET / → 200;② 数据库链路探测用「活动页响应时间」——正常毫秒级,DB 不可达时稳定 10.0s(Q5 特征),把 GET /<已知eventID> 的 time_total > 5s 作为告警阈值最实用;③ 崩溃循环看 docker inspect --format '{{.RestartCount}}' 是否增长。

六、参考链接

Gathio 1.6.7 排错FAQ - Quzuo