{"record":{"id":"b0ed27e1dae116f6","repo":"unionlabs/union","slug":"unknown-ibc-spec-ibc-spec-id","errorCode":null,"errorMessage":"unknown IBC spec `{ibc_spec_id}`","messagePattern":"unknown IBC spec `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"voyager/src/main.rs","lineNumber":492,"sourceCode":"                        .await?;\n\n                    print_json(&client_info);\n                }\n                RpcCmd::ClientState {\n                    on,\n                    client_id,\n                    ibc_spec_id,\n                    height,\n                    decode,\n                } => {\n                    let ibc_state = voyager_client\n                        .query_ibc_state(\n                            on.clone(),\n                            ibc_spec_id.clone(),\n                            height,\n                            (ibc_handlers\n                                .get(&ibc_spec_id)\n                                .context(anyhow!(\"unknown IBC spec `{ibc_spec_id}`\"))?\n                                .client_state_path)(client_id.clone())?,\n                        )\n                        .await?;\n\n                    match (ibc_state.state, decode) {\n                        (Some(state), true) => {\n                            let client_info = voyager_client\n                                .client_info(on, ibc_spec_id.clone(), client_id)\n                                .await?\n                                .ok_or(anyhow!(\"client info not found\"))?;\n\n                            let decoded = voyager_client\n                                .decode_client_state(\n                                    client_info.client_type,\n                                    client_info.ibc_interface,\n                                    ibc_spec_id,\n                                    serde_json::from_value(state)\n                                        .expect(\"serialization is infallible; qed;\"),","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/voyager/src/main.rs#L474-L510","documentation":"For `voyager rpc client-state --decode`, the CLI must build the on-chain storage key for the client state itself, using a local map `ibc_handlers` keyed by IBC spec ID. That map is hardcoded at voyager/src/main.rs:422-427 to exactly two entries: `IbcClassic::ID` (\"ibc-classic\") and `IbcUnion::ID` (\"ibc-union\"). Passing any other `--ibc-spec-id` makes `HashMap::get` return `None`, and `.context(anyhow!(...))` attaches this message.","triggerScenarios":"Running `voyager rpc client-state --on <chain> --client-id <id> --ibc-spec-id <spec> --decode` with a spec ID other than `ibc-classic` or `ibc-union` (e.g. `ibc-grandpa`, a chain-specific custom spec, or a typo like `ibc_classic`). Note the raw query without `--decode` also needs the handler for the path, so any spec outside the two built-ins fails here.","commonSituations":"Adding support for a new/custom IBC spec handler on the server side (via `register_ibc_spec_handler`) while the CLI build in use predates it; typo'd spec IDs in scripts; version skew between the CLI and the voyager server that registered extra spec handler plugins.","solutions":["Use one of the two supported spec IDs: `ibc-classic` (ICS-07 tendermint-style clients) or `ibc-union` (Union's cometbft-client/ics08-wasm style paths).","Check for typos in the flag value; the IDs are kebab-case and case-sensitive.","If you need a spec beyond the two built-ins, the CLI must be rebuilt from a tree where your spec is added to the `ibc_handlers` map in voyager/src/main.rs:422 (e.g. `(MySpec::ID, IbcSpecHandler::new::<MySpec>())`).","If you expected the running server's registered handlers to apply, verify CLI/server versions match — the map is local to the CLI, not fetched from the server."],"exampleFix":"# before\nvoyager rpc client-state --on cosmos-hub --client-id 07-tendermint-0 --ibc-spec-id tendermint --decode\n# error: unknown IBC spec `tendermint`\n\n# after\nvoyager rpc client-state --on cosmos-hub --client-id 07-tendermint-0 --ibc-spec-id ibc-classic --decode","handlingStrategy":"validation","validationCode":"case \"$IBC_SPEC_ID\" in ibc-classic|ibc-union) ;; *) echo \"unsupported spec: $IBC_SPEC_ID\" >&2; exit 2;; esac","typeGuard":"fn is_known_ibc_spec(id: &str) -> bool {\n    matches!(id, \"ibc-classic\" | \"ibc-union\")\n}","tryCatchPattern":null,"preventionTips":["Use the CLI's `--ibc-spec-id` values verbatim from documentation and completion output.","Centralize spec-id constants in scripts (one variable per spec) to avoid typos.","When adding a custom spec handler server-side, add it to the CLI `ibc_handlers` map in the same PR.","Keep CLI and server built from the same commit so supported specs match."],"tags":["rust","cli","ibc","validation","voyager"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}