Meme Atlas AZ · research-ledger-states
代幣資料 API 回傳 null 或查不到,該記成 0、留白還是不存在?
空值在回應裡有好幾種長相,意思跟著方法與欄位走;研究紀錄要抄下它的形狀,分開寫查到的、推斷的與未解的,並替每一次失敗留下重查入口。
- 發布
- 更新
- 編輯責任
- Meme Atlas AZ
做代幣資料研究,遲早會碰到一格填不下去的欄位:供應量回來是空的,地址查不到程式碼,資料源乾脆報錯。手邊通常只有三個選項——寫 0、留白、寫「不存在」。三個都不太對,錯的方向還各不相同。
三種填法會把接手的人帶向不同的下一步:拿去加總、回頭重查,或就此結案;所以先要看清手上的「空」長什麼樣。
2026-09-27 的一次查詢,對著同一個 Solana 公共節點、同一把隨機產生且從未用過的公鑰,接連問了兩件事。先問帳戶資訊(getAccountInfo),回來的是正常結果,帶著節點當時所在的 slot,value 那一格是 null。緊接著把它當成代幣去問供應量(getTokenSupply),這次沒有結果,只有錯誤物件,代碼 -32602,訊息寫著 "Invalid param: could not find account"。同一個「沒有」,一次落在結果層、帶著時間座標;一次落在錯誤層,什麼座標都沒留。
這只是單一節點、單一時刻的觀察,不代表那個服務總是這樣回;本文讀到的 getTokenSupply 文件沒寫 mint 不存在時該回什麼,Solana 集中列出錯誤碼的頁面,這次也沒查到。但它足以說明「回傳空」不是一種狀態。該記的是空的形狀,以及它落在回應的哪一層。
null、0x 與 []:回應裡的「空」長成哪些樣子
開頭那兩次回應,一次是 result 裡的 null,一次是代碼 -32602 的錯誤物件,JSON-RPC 2.0 規範兩種都容得下:它要求 "Either the result member or error member MUST be included, but both members MUST NOT be included."(本文所引英文句子皆為原文,中文說明是本文轉述;ethereum.org 的引文用其官方繁中譯本),result 的值則 "determined by the method invoked on the Server"。所以 null 代表什麼,得回到那個方法的文件去讀;按已讀的官方文件,空至少有下面幾種長相。
整個結果就是 null
ethereum.org JSON-RPC 文件的官方繁中譯本寫得很直接:查區塊時回傳「一個區塊物件,如果未找到區塊則回傳 null」;查收據時是「交易收據物件,如果找不到收據則回傳 null」。執行層規格(ethereum/execution-apis)替這種 null 取了名字,型別標題就叫 "Not Found (null)",區塊類查詢的結果寫成 notFound 與 Block 二選一。Solana 的 getAccountInfo 也一樣,文件說帳戶在所請求的 commitment 下不存在時 value 為 null,只是包在帶 slot 的外殼裡。
沒有結果,只有錯誤物件
錯誤物件有 code 與 message,另可附 data。規範的預定義錯誤碼表裡,沒有任何一行叫「資料不存在」:-32601 "Method not found" 說的是方法不存在,不是資料不存在;-32000 到 -32099 則保留給各實作自行定義。開頭那次 getTokenSupply 把「找不到帳戶」放進了 -32602,而這個代碼在規範表裡的名字是 "Invalid params"。
值在,但裡面是空的
以太坊的 eth_getCode,規格把回傳值定為十六進位位元組字串,允許 0x 後面什麼都沒有;規格自帶的測試樣例裡,向不存在的帳戶要程式碼,預期回應正是 0x。ethereum.org 的方法說明沒寫無程式碼的地址會回什麼。0x 能否區分「從未出現過的地址」「普通外部帳戶」「曾有合約、程式碼已移除」,這次沒查到出處,不能把 0x 讀成其中任何一種。Etherscan 查合約原始碼的端點另有一種空字串:文件寫 SourceCode 在合約未驗證時為空。這格空的意思是「未驗證」。
一個空陣列
2026-09-27 的一次查詢,向 CoinGecko 免金鑰的行情列表要一個不存在的幣種代號,回來的正文是 [];改問單一幣種詳情,回來的是一個寫著 "coin not found" 的錯誤物件。同一件「查無此幣」,兩個端點兩種形狀。CoinGecko 錯誤頁的兩張錯誤表都沒有講幣種不存在的一行,這兩種形狀只能記成那一次的觀察。
欄位乾脆不在
Solana 的 JSON 結構文件裡,「沒有」有兩種寫法並存:交易的 meta 在資料不可得時給 null;version 則在版本資訊不可得時直接省略。還有一種省略來自問法本身——以 accounts 模式取區塊時,innerInstructions、logMessages 等欄位被 "intentionally omitted"。欄位不在,可能只是換了請求模式。
同一個 null,換一格就換一個意思
認出形狀之後,還要看它長在哪一格。同一份 Solana 文件裡,帳戶查詢的 value 為 null 表示帳戶不存在;交易狀態的 err 為 null,文件寫的卻是 "null means the transaction succeeded"——沒有錯誤,也就是成功。兩個 null,意思正好相反。
以太坊的交易物件也是如此。官方繁中譯本寫 blockNumber「如果處於待處理狀態則為 null」,to「如果是合約創建交易則為 null」。兩者都跟「查不到」無關。
資料商的規格裡,null 常常就是正常形狀。CoinGecko 行情列表的回應規格把 current_price、circulating_supply、max_supply 等欄位同時列為 required 與 nullable:required 管的是鍵一定在,nullable 管的是值可以為 null。鍵在、值空是規格允許的回應;欄位說明沒交代為何是 null,就別替它補理由。這份規格標示的是 Pro 版,免費版是否逐欄相同,留待下次核對。DEX Screener 交易對查詢的規格把整個 pairs 陣列標為可為 null;2026-09-27 的一次查詢拿一個不是池子的地址去問,回來 pairs 為 null,旁邊還多了一個規格沒定義的 pair 欄位。回應長出規格外的欄位,本身就值得原樣記下。
「0」也有同樣的問題。Etherscan 列表端點這樣描述 status:"1 if the request returned data, 0 otherwise. A status of 0 can indicate an error or a valid request that returned no records." 查詢失敗與合法地查到零筆,在 status 上是同一個 0,message 與 result 的原文必須一起留。零筆紀錄時 message 與 result 實際寫什麼,尚待查證。
抄空值因此要連三樣一起抄:哪個方法、哪一格、哪種形狀。
規格把 null、-32001 與 4444 分成三種「查不到」
「尚未取得」與「確定不存在」要分開記,規格層找得到現成依據。
執行層規格裡有一個較新的方法 eth_getBlockAccessList,說明文字把三種情況寫成三種回應:區塊未知或請求 pending 時結果為 null;區塊早於 Amsterdam 分叉時,客戶端必須回 "-32001: Resource not found";區塊的存取清單已被修剪時,必須回 "4444: Pruned history unavailable"。代幣研究用不到它,舉它只因它把「未知」「不適用」「曾有但已刪」並排寫清楚了。同一份規格也替 eth_getBlockByNumber、eth_getBlockReceipts 等區塊查詢列了 4444 這個錯誤;哪些客戶端或服務商實際會回它、從哪個版本起,目前手上沒有出處。
反方向的提醒來自 EIP-4444。這份目前狀態仍是草案(Draft)的提案,允許客戶端在本地修剪較舊的區塊頭、區塊體與收據,並直說屆時某些查詢 "won’t be able to tell whether a given hash is invalid or just outdated",應用端怎麼處理則在提案範圍之外。它不能讀成「以太坊已全面修剪歷史」,但足以說明:節點回 null,最多說明這個節點在那一刻手上沒有這筆資料。
HTTP 層也差不多。RFC 9110 說 404 表示伺服器沒找到目標資源的現行表示,或不願透露它存在,且不表明缺席是暫時還是永久;伺服器還可以用 404「隱藏」被禁止存取的資源。410 才表示很可能永久,但伺服器沒有義務使用它。
合起來看,大多數空值只配寫成「這個來源、在這一刻,沒有給出」。
很多「取不到」跟資料本身無關:方案、429 與逾時
失敗紀錄要分類,因為不少失敗描述的是請求者自己的處境,跟那枚代幣無關。按官方文件,至少分得出下面幾類。
身分與方案
CoinGecko 的錯誤碼 10005 寫的是 "Endpoint not available on your plan."。Etherscan 對部分鏈寫 "Free API access is not supported for this chain.",在測試網上呼叫 Pro 端點也會報錯。2026-09-27 一次不帶金鑰的 Etherscan 查詢,回來的是 status 為 "0"、result 為 "Missing/Invalid API Key"。這幾種都只說明以這個身分查不到。
頻率
CoinGecko 寫明所有請求都計入每分鐘限額,"including 4xx and 5xx errors";免金鑰的用法按 IP 計算,同一個 IP 上的使用者共用。Etherscan 某條鏈的共享免費額度,也是那個池裡所有使用者累計,不綁個別金鑰。Solana 的 RPC 概述則說,公共端點超過限額時可能回 429,流量被擋時可能回 403。具體次數與秒數會變,本文不寫,要用時回各家的限額頁看。
服務端
RFC 9110 的 503 表示暫時過載或維護中,但同一節也提醒,伺服器過載時不一定回 503,可能直接拒絕連線。2026-09-27 同一時刻、同一批問題送到兩個以太坊公共節點,一個照常作答,另一個對三個請求全回 -32603 "Internal error"。這只是一次觀察,不能據此說那個節點不能用;它說明「這次沒拿到」和「鏈上沒有」之間隔著好幾層。
查詢太大
Etherscan 對逾時錯誤的說明是 "This error occurs when you have sent a particularly large query that did not manage to be completed in time.",給的處理是縮小日期或區塊範圍。
一次查詢,拆成 observed、inferred、unresolved 三層寫
observed、inferred、unresolved 是本站研究紀錄沿用的三層寫法,大意是觀察到的、推斷的、未解的;這不是任何官方文件的分類。拿開頭那次 getAccountInfo 來示範,三層分別寫什麼:
- observed:哪個節點、哪一級 commitment、回應自帶的 slot、value 為 null。這一層只收回應裡直接出現的東西。
- inferred:在那個 commitment、那個 slot 上,這個節點沒有這個帳戶。推斷要註明倚賴哪幾格,這裡倚賴的是 value 與 context.slot。
- unresolved:這把公鑰是否從來沒在鏈上出現過。一個節點的一次 null 回答不了,就留在這一層,並寫下還缺什麼證據。
observed 要抄 commitment 與 slot,是因為 Solana 文件說 processed 讀的是節點眼中最新的視圖,"it can still change if the cluster switches forks";以太坊那邊,官方繁中譯本寫「當發出查詢以太坊狀態的請求時,提供的區塊參數決定了區塊的高度。」少了這些,重查時就無從判斷比對的是不是同一刻。
三層之外還有一條:失敗本身也是一筆 observed。沒拿到結果的那一次,照樣記下時間、來源、錯誤形狀與原文,和成功的讀數放在同一頁。
重查入口:先從 Retry-After 與回應本身找
失敗紀錄最後一格寫「下次從哪裡查」,很多時候回應已經給了線索。
- 時間:RFC 9110 說 503 可以附 Retry-After,值是一個 HTTP 日期或一個延遲秒數;RFC 6585 說 429 也可以附上。各家資料服務在 429 或 503 時實際帶不帶這個標頭,這次一家都沒確認,所以有就照抄,沒有就寫沒有。
- 範圍:查詢太大而逾時,重查入口就是一個更小的區塊或日期範圍。
- 分辨故障:Etherscan 服務狀態頁的分辨法是,result 回來一個區塊號,表示服務正常、金鑰有效;result 裡是錯誤,問題在自己的請求或金鑰;再看當日可用與已用的呼叫數,分出是被限流還是服務故障。
- 來源:換了節點或資料源,記下換了什麼,並標明新讀數與上次不是同一條路取得。
- 次數:至少 CoinGecko 寫明錯誤請求也計入限額,RFC 6585 又規定 429 回應不得被快取,要記下上次何時試、試了幾次。
最後要容許一件事:有些格子可以一直停在 unresolved。若手上的節點都已修剪歷史,EIP-4444 草案自己就承認某些查詢分不出雜湊是無效還是過舊,並把歷史資料由獨立組織保存、定期檢查可用性的機制列在提案範圍之外。碰到這種格子,照實寫「目前的來源回答不了」,附上試過哪些來源。比起寫 0、留白或寫「不存在」,這更貼近手上真正有的東西;接手的人也會知道,這一格等的是新證據,而不是更用力的重試。
內容來源
- JSON-RPC 2.0 Specification發布者: JSON-RPC Working Group查閱日期:
- ethereum.org — JSON-RPC API發布者: ethereum.org查閱日期:
- ethereum.org — JSON-RPC API (zh-tw)發布者: ethereum.org查閱日期:
- Ethereum execution-apis — schemas/base-types.yaml發布者: ethereum/execution-apis (GitHub)查閱日期:
- Ethereum execution-apis — eth/block.yaml發布者: ethereum/execution-apis (GitHub)查閱日期:
- Ethereum execution-apis — eth/state.yaml發布者: ethereum/execution-apis (GitHub)查閱日期:
- Ethereum execution-apis — test: get-code-unknown-account發布者: ethereum/execution-apis (GitHub)查閱日期:
- EIP-4444: Bound Historical Data in Execution Clients發布者: Ethereum Improvement Proposals查閱日期:
- Solana Docs — getAccountInfo發布者: Solana Foundation查閱日期:
- Solana Docs — getTokenSupply發布者: Solana Foundation查閱日期:
- Solana Docs — JSON Structures發布者: Solana Foundation查閱日期:
- Solana Docs — RPC Overview發布者: Solana Foundation查閱日期:
- CoinGecko API — Coins List with Market Data發布者: CoinGecko查閱日期:
- CoinGecko API — Errors & Rate Limits發布者: CoinGecko查閱日期:
- DEX Screener — API Reference發布者: DEX Screener查閱日期:
- Etherscan API — txlist發布者: Etherscan查閱日期:
- Etherscan API — getsourcecode發布者: Etherscan查閱日期:
- Etherscan API — Common Error Messages發布者: Etherscan查閱日期:
- Etherscan API — API Status發布者: Etherscan查閱日期:
- RFC 9110: HTTP Semantics發布者: RFC Editor (IETF)查閱日期:
- RFC 6585: Additional HTTP Status Codes發布者: RFC Editor (IETF)查閱日期: