Tất cả bài viết
9 phút đọc

TON liteserver báo "not ready": nguyên nhân và cách khắc phục

TON liteserver trả về "not ready" hoặc ADNL timeout? Phân tích nguyên nhân trên config công khai và cách dứt điểm lỗi bằng retry và key hosted TONNode.

TONliteserverADNLnot readyMCPnode TON

Liteserver not ready: bạn gửi một request đơn giản — và nhận về "not ready"

Bạn đang viết một agent cần kiểm tra số dư ví hoặc gọi get-method của contract. Code đúng, địa chỉ đúng, config liteserver lấy thẳng từ global-config.json chính thức. Vậy mà thay vì câu trả lời, bạn liên tục nhận về lúc thì not ready, lúc thì chẳng có gì cả — kết nối cứ treo rồi rụng vì ADNL timeout. Mà nó cũng chẳng phải lúc nào cũng tái hiện được: sáng thì chạy ngon, cứ vào tải là hỏng. Nghe quen chứ? Đây không phải bug trong code của bạn, cũng chẳng phải "TON sập". Đây là hành vi hoàn toàn dự đoán được của các public liteserver trong global config. Hãy cùng mổ xẻ vì sao TON liteserver not ready lại xảy ra, cái gì thật sự có tác dụng ở phía client — và cái gì thì không.

"not ready" và ADNL timeout của TON liteserver thực chất là gì

not ready là câu trả lời thẳng thắn của liteserver: "tôi chưa sync xong, tôi chưa trả lời bạn được". TON có hai tầng blockchain: masterchain và basechain (workchain 0), và basechain lại chia thành các shardchain, hay còn gọi là shard. Masterchain giống như mục lục của một cuốn sách, còn shard là chính các chương chứa giao dịch và trạng thái account. Node thường nhận được head của masterchain trước khi kịp đuổi theo các shard block tương ứng. Ngay thời điểm đó, masterchain đang chạy trước basechain, còn trạng thái account thì nằm trong shard block mới nhất — và tạm thời chưa thể kiểm tra được nó. Thế nên node thành thật trả về not ready thay vì đưa cho bạn dữ liệu cũ hoặc thiếu.

ADNL timeout là một triệu chứng khác của đúng căn bệnh đó. ADNL là protocol truyền tải gốc của TON, là cách liteserver nói chuyện với client (hoàn toàn không có HTTP ở đó). Khi node quá tải, nó đơn giản là không đáp lại request ADNL trong khung thời gian cho phép, và client rụng vì timeout trước cả khi chạm tới logic nghiệp vụ.

Ở đây, quan trọng là đừng lẫn lộn các tầng với nhau. not ready và ADNL timeout sống ở tầng protocol ADNL gốc của liteserver. Nó không giống HTTP 429 Too Many Requests — mã mà các HTTP gateway như toncenter và tonapi.io trả về khi bạn vượt giới hạn. Khác tầng, khác mã, khác nguyên nhân. Nếu thứ bạn đang vật lộn đúng là 429 thì đó lại là một câu chuyện riêng: bài phân tích cách fix 429 của toncenter. Còn cái meme "lỗi 228" trong các nhóm chat TON là trò đùa của cộng đồng chứ không phải mã thật; liteserver không bao giờ trả về nó.

Vì sao public liteserver trong global config gục khi có tải

Gốc rễ của vấn đề rất đơn giản. Các liteserver trong ton.org/global-config.jsondùng chung và bị giới hạn. Đó là tài nguyên công cộng mà hàng nghìn lập trình viên, bot, indexer và agent khắp thế giới cùng lúc đổ vào. Một tài nguyên như vậy có ba giới hạn mang tính hệ thống:

  • Tải dùng chung. Bạn chia pool đó với cả hệ sinh thái. Vào giờ cao điểm, node hoặc là không kịp đuổi theo head của mạng (từ đó sinh ra not ready), hoặc đơn giản là không trả lời kịp (ADNL timeout).
  • Không có lịch sử sâu. Public node không lưu archive sâu. Nếu bạn cần một giao dịch cũ theo cặp lt/hash, rất có thể nó chẳng còn ở đó nữa — chuyện làm việc với lịch sử có một bài riêng về lt và hash.
  • Không hề có bảo đảm. Đây là tài nguyên kiểu "có sao dùng vậy". Bạn không có quyền ưu tiên, cũng chẳng ai hứa hẹn băng thông nào cho bạn: hôm nay may, mai thì không.

Nói cách khác, not ready không phải chuyện ngẫu nhiên có thể "đợi cho qua", mà là hành vi tất yếu của một tài nguyên dùng chung khi có tải. Và chẳng dòng code nào của bạn ép được con node quá tải của người khác sync nhanh hơn.

Fix phía client: retry, xoay vòng endpoint và timeout

Trước khi động vào hạ tầng, hãy vắt kiệt những gì client làm được. Các kỹ thuật này có tác dụng thật, nhưng chúng có trần — dù sao node vẫn cứ là hàng dùng chung.

1. Retry với exponential backoff

not ready thường chỉ thoáng qua: sau 200–800 ms chính con liteserver đó đã apply xong đúng shard block nó còn thiếu. Chỉ một lần thử lại với độ trễ tăng dần cũng cắt được một phần đáng kể số lỗi.

async function withRetry<T>(fn: () => Promise<T>, tries = 4): Promise<T> {
  let lastErr: unknown;
  for (let i = 0; i < tries; i++) {
    try {
      return await fn();
    } catch (e) {
      lastErr = e;
      // retry 'not ready' và ADNL timeout, nhưng không retry lỗi nghiệp vụ
      await new Promise((r) => setTimeout(r, 200 * 2 ** i));
    }
  }
  throw lastErr;
}

2. Xoay vòng endpoint

Hãy giữ sẵn trong pool vài liteserver lấy từ config và chuyển sang con kế tiếp nếu con hiện tại trả not ready hoặc rơi vào timeout. Một node đang tụt lại — con bên cạnh có thể đã đuổi kịp rồi.

3. Nới timeout

ADNL timeout mặc định đôi khi quá gắt với một public node đang quá tải. Nới thêm một chút (vài giây) sẽ giảm bớt những lần đứt kết nối oan. Nhưng nếu kéo timeout lên vô tận thì bạn chỉ đang tích lũy đống request treo; đó không phải chữa bệnh, mà là gây tê.

Một mẹo riêng rất hữu ích là healthcheck nhẹ trước request thật. get_masterchain_info (head của masterchain) hợp vai này hoàn hảo: chính thao tác này là thứ đầu tiên trả về seqno mới khi node đã đuổi kịp head của mạng, và nó chỉ trả not ready khi node còn chưa đuổi kịp chính head của masterchain. Đã trả về seqno mới nghĩa là node đang khỏe, có thể gọi get_account_state, get_balance, run_get_method.

Kết luận thành thật: retry + xoay vòng + timeout kéo tần suất lỗi xuống, nhưng không xóa được nguyên nhân. Public node quá tải by design — bạn chỉ đang gõ cửa lịch sự hơn thôi, còn sau cánh cửa vẫn là đúng cái hàng dài đó. Các hướng tiếp cận khác để truy cập TON được tổng hợp trong bài các lựa chọn thay thế toncenter cho 2026.

Giải pháp không cần tự dựng node: key hosted TONNode trên liteserver của chúng tôi

Chỉ có đúng một cách gỡ not ready tận gốc — thôi không đi vào các node dùng chung nữa. Tự dựng rồi tự nuôi một node TON riêng thì vừa đắt vừa nhọc: sync, ổ đĩa, cập nhật, giám sát. Phương án trung gian là không đi vào pool chung, mà nhận băng thông được đảm bảo cùng quyền truy cập ưu tiên thông qua một key.

TONNode là một MCP server hosted cho TON. MCP (Model Context Protocol) là chuẩn để các AI agent (Claude, Cursor, ChatGPT/Codex, mọi MCP client) gọi tool. Thay vì để code của bạn tự parse global config rồi nhảy múa quanh not ready, agent gọi một tool dựng sẵn, và đằng sau nó là endpoint hosted https://mcp.tonnode.io/mcp với Bearer key của bạn. Đó là băng thông được đảm bảo thay cho một hàng đợi dùng chung.

Package @tonnode/mcp — open source (MIT, có trên npm và GitHub tonnode/mcp) — chạy theo protocol ADNL gốc của TON, không có lớp HTTP trung gian. Nghĩa là bạn không phải đổi transport sang một HTTP gateway chậm chạp, mà vẫn ở lại đúng cái ADNL tử tế đó — chỉ khác là có quyền ưu tiên gắn với key của bạn.

Để chẩn đoán và đọc dữ liệu hằng ngày, những tool sau sẽ có ích:

  • get_masterchain_info — head của masterchain, healthcheck tự nhiên nhất.
  • get_account_state — trạng thái, cờ và giao dịch cuối cùng của account.
  • get_balance — số dư tính bằng GRAM.
  • run_get_method — bất kỳ get-method read-only nào của contract.

Nếu bạn mới bắt đầu với MCP trên TON, hãy nắm nền qua hướng dẫn MCP cho TON.

Cách kết nối: npx chạy local hoặc endpoint hosted kèm key

Miễn phí, chạy local

Toàn bộ bộ tool đọc dữ liệu chạy được ngay từ local, theo config công khai, không cần thẻ và không cần key:

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Cách này rất hợp để phát triển và thử nghiệm cục bộ. Nhưng nhớ rằng: npx chạy local bên dưới vẫn đi vào đúng những liteserver dùng chung đó, nên nó không cứu bạn khỏi not ready khi có tải — nó cứu bạn khỏi việc loay hoay với dependency và cho bạn một interface tool thống nhất.

Hosted kèm key

Để rời khỏi các node dùng chung, hãy chuyển transport sang HTTP-MCP với Bearer key riêng của bạn (bản thân lời gọi tool sẽ đi tới node của chúng tôi qua ADNL):

{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer tn_live_…" }
    }
  }
}

Trông ra sao khi làm việc với agent

Sau khi kết nối, agent chỉ cần một prompt bình thường — tool thì nó tự chọn:

Đầu tiên gọi get_masterchain_info để healthcheck. Sau đó get_account_state cho EQC… — cho tôi xem trạng thái và giao dịch cuối cùng. Rồi get_balance cho cùng địa chỉ đó.

Bên dưới đó là một chuỗi: get_masterchain_info (node còn sống và đã đuổi kịp head của mạng) → get_account_state (trạng thái, cờ, giao dịch cuối) → get_balance (số dư GRAM). Không còn màn retry vòng quanh hàng đợi của người khác — request đi thẳng vào băng thông được đảm bảo. Nhân tiện, GRAM chính là Toncoin đã đổi tên (việc đổi tên diễn ra vào tháng 6/2026); còn mạng lưới thì vẫn gọi là TON.

Key Hobby miễn phí (60 request/phút) được cấp ngay sau khi đăng nhập, không cần thẻ. Về sau khi lớn dần: Pro — $29/tháng, 300 request/phút; Scale — $199/tháng, 1200 request/phút. Một chi tiết quan trọng: ở mọi gói cước đều có đủ 16 tool của TONNode — bạn chỉ trả tiền cho băng thông, chứ không phải cho tính năng.

Liteserver riêng dành cho bạn — theo yêu cầu, không phải self-serve

Đôi khi gói hosted vẫn chưa đủ và bạn cần một liteserver dành riêng (single-tenant) — chỉ phục vụ traffic của bạn, không có hàng xóm nào cả. Phương án đó có tồn tại, nhưng nói thẳng: nó không phải kiểu self-serve. Không có nút "bật single-tenant" nào trong dashboard cả — chuyện này được xử lý thủ công: hãy liên hệ với chúng tôi, cùng bàn về mức tải và cấu hình.

Và thêm một lời nói thẳng nữa về độ sâu lịch sử. Archive node của TONNode hiện đang sync và chưa phục vụ request. "Độ sâu archive" là một mục trong roadmap, chứ không phải tính năng đã sẵn sàng. Nếu ngay hôm nay bạn cần lịch sử sâu trọn thời gian, hãy lên kế hoạch riêng cho việc đó. Cái gì đã sẵn sàng và cái gì còn nằm trong dự định — xem ở roadmap.

Tóm tắt nhanh

  • not ready = node chưa sync xong: masterchain đang chạy trước shard, trạng thái account nằm ở shard block mới nhất nên chưa thể kiểm tra.
  • Public liteserver trong global config là dùng chung và bị giới hạn: not ready, ADNL timeout, không có lịch sử sâu. Đừng lẫn nó với HTTP 429 của toncenter/tonapi — khác tầng.
  • Các fix phía client (retry với backoff, xoay vòng endpoint, timeout) giảm tần suất lỗi, nhưng không xóa được nguyên nhân.
  • get_masterchain_info là healthcheck của bạn: nó chỉ báo đỏ not ready khi node hoàn toàn chưa đuổi kịp head của masterchain.
  • Cách chữa thật sự là rời khỏi tài nguyên dùng chung để sang băng thông được đảm bảo.

Hãy lấy key Hobby hosted miễn phí và thôi dính "not ready" trên các node dùng chungtonnode.io/dashboard?plan=hobby

Về sau khi tải tăng dần — bảng giároadmap.

Cho agent của bạn quyền truy cập TON

16 công cụ MCP: đọc, swap phi lưu ký, cross-chain và ví. Gói miễn phí — 60 req/phút, không cần thẻ.