Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Error 463 permanent on cold sends for instances paired before v0.7.2 — NCT salt never backfilled

未关闭
#124 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 5 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
55/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
冷清
技术栈
go, postgresql
领域
backend

调研方向

从 events.Connected 路径和 handleAppStateSyncKeyShare 开始,然后检查 cstoken.go、message.go 以及 issue 中描述的 NCT salt 存储行为。将常规的 regular_high FetchAppState 调用与建议的强制 bootstrap 进行比较,并验证一个 salt 为空的 pre-v0.7.2 实例可以恢复 cold sends,而不会无限期地重复 bootstrap。

由索引模型根据 Issue 内容生成。

描述

Summary

Instances that were paired before v0.7.2 (when the project dropped the custom whatsmeow-lib fork and switched to official upstream go.mau.fi/whatsmeow) never receive the NCT salt, and therefore can never generate a <cstoken> for first-contact (cold) 1:1 sends. This makes error 463 (NackCallerReachoutTimelocked) permanent for any pre-v0.7.2 instance trying to message a number it has never talked to before — it never self-heals, no matter how many times the instance reconnects.

Root cause

  • generateCsToken (whatsmeow cstoken.go) requires cli.Store.NCTSalt.GetNCTSalt(ctx) to return a non-empty salt. We confirmed via direct Postgres inspection that whatsmeow_nct_salt is completely empty (0 rows) for an instance that has been connected and working for months.
  • The salt is only delivered through two whatsmeow-internal paths: (1) the one-time History Sync payload sent right after a fresh QR pairing (message.go, historySync.GetNctSalt()), or (2) an App State Sync patch (regular_high category, nct_salt_sync mutation index) fetched via FetchAppState.
  • Instances paired before v0.7.2 went through their one-time History Sync using the old custom fork, which had no concept of NCT salt at all — that one-time opportunity is gone forever for those instances.
  • Going forward, regular_high should self-heal via handleAppStateSyncKeyShare, but that function calls FetchAppState(ctx, name, false, onlyResyncIfNotSynced=true) — and onlyIfNotSynced skips categories that already have some stored version, even if that version predates cstoken support and never actually captured the salt mutation. So already-synced-but-stale categories are never re-fetched, and the instance is stuck permanently.

How Baileys solved the identical problem

Baileys hit the exact same gap and fixed it in WhiskeySockets/Baileys#2438 with a dedicated ensureNctSaltSynced() (in chats.ts): on every connection.update → open, if no salt is stored yet, it force-fetches regular_high on its own — independent of the normal "already synced" gating, guarded on the persisted regular_high version so it bootstraps at most once and never loops for accounts that legitimately have no salt yet.

Suggested fix

Port the equivalent of ensureNctSaltSynced() into evolution-go (or ideally into go.mau.fi/whatsmeow itself, so all consumers benefit): on events.Connected, if cli.Store.NCTSalt.GetNCTSalt(ctx) is empty, call cli.FetchAppState(ctx, appstate.WAPatchRegularHigh, true, false) once (forcing fullSync=true, onlyIfNotSynced=false specifically for this bootstrap case), guarded so it only runs once per process/instance to avoid loops for accounts that genuinely have no salt provisioned server-side yet.

Impact

Affects any instance paired before the org's whatsmeow upgrade (in our case, before 2026-07-03 / v0.7.2). For anyone doing bulk migrations of older instances (e.g. from a different provider) into evolution-go, this silently breaks first-contact/cold outreach sends indefinitely, with no error message pointing at the actual cause (surfaces only as server returned error 463 on /send/text, identical to the generic reach-out time-lock).

Environment

  • evolution-go v0.7.2 (go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b)
  • Instance paired 2026-02-18 (pre-v0.7.2, custom whatsmeow-lib fork era)
  • Confirmed via direct query: whatsmeow_nct_salt = 0 rows, whatsmeow_privacy_tokens = 0 rows for the affected contact, whatsmeow_lid_map correctly populated (so LID resolution is not the issue)
主要语言
Go
星标
890
派生
473
PR 合并指标
30 天内没有已合并 PR

环境准备

  • 提供 Dockerfile 或 Docker Compose 文件
  • 有 Pull Request 模板
  • 没有贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

evolution-foundation/evolution-go 的其他 Issue

查看 evolution-foundation/evolution-go 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。