Skip to main content

Troubleshooting

This page documents common issues encountered when building on or operating Specter, along with their causes and solutions.

Chain ID 47474 Instead of 5446

Symptoms:

  • Wallet balance shows 0 despite receiving tokens from the faucet or transfers.
  • Transactions fail or are rejected by the RPC.
  • MetaMask shows the wrong network name.

Cause: An earlier Avalanche L1 deployment of Specter used Chain ID 47474. That chain is deprecated. The current Specter Testnet uses Chain ID 5446 (0x1546).

Solution:

  1. Open MetaMask and remove the old network entry with Chain ID 47474.
  2. Add a new network with the correct parameters:
    • RPC URL: https://testnet.specterchain.com
    • Chain ID: 5446
    • Symbol: GHOST
    • Decimals: 18
  3. If building a dApp, update your chain configuration (hardcoded chain IDs, wagmi config, etc.) to use 5446.

Using testnet-rpc.umbraline.com

Symptoms:

  • RPC requests intermittently fail or time out.
  • Block numbers are behind the current chain head.
  • Transaction submissions succeed but never confirm.

Cause: The testnet-rpc.umbraline.com endpoint may point to a stale or unmaintained node that is no longer syncing with the current chain.

Solution:

  • Switch to the primary RPC endpoint: https://testnet.specterchain.com.
  • The https://testnet.umbraline.com endpoint (without the -rpc prefix) is also valid and maintained.
  • Update all configuration files, scripts, and environment variables to use the correct endpoint.

Go 1.24.0 Build Error (Sonic / bytedance linkname)

Symptoms: When building the Specter node binary with Go 1.24.0, the build fails with errors related to go:linkname directives in the bytedance/sonic package:

github.com/bytedance/sonic/internal/rt: //go:linkname must refer to declared function or variable

Cause: Go 1.24.0 introduced stricter enforcement of the //go:linkname compiler directive. The bytedance/sonic JSON library (a transitive dependency via the Cosmos SDK dependency tree) uses //go:linkname to access internal Go runtime symbols, which the stricter compiler rejects.

Solution:

  • Upgrade to Go 1.24.1 or later, which relaxes the linkname restrictions for existing code.
  • Alternatively, you can set GOFLAGS=-ldflags=-checklinkname=0 as a temporary workaround, but upgrading Go is the recommended fix.
# Check your Go version
go version

# If go1.24.0, upgrade
# macOS with Homebrew:
brew upgrade go

# Or download directly:
# https://go.dev/dl/

# Verify
go version
# go version go1.24.1 darwin/arm64

# Clean and rebuild
cd specter-chain
go clean -cache
make build

eth_getLogs Returns Empty Results

Symptoms:

  • Calls to eth_getLogs return an empty array even though events were emitted.
  • Event-based indexing (e.g., watching for CommitmentInserted events) misses events.
  • The webapp's Revels screen shows no history.

Cause: This is a known limitation of the Cosmos EVM implementation. The EVM module's log indexing is not fully compatible with Ethereum's eth_getLogs behavior, particularly for historical queries and large block ranges.

Solution:

  • Use the Specter relayer indexer instead of eth_getLogs for reliable event queries:
curl "https://relayer.specterchain.com/api/indexer?event=CommitmentInserted&fromBlock=0&toBlock=latest"
  • For real-time event monitoring, subscribe via WebSocket if supported, or poll the indexer API at regular intervals.
  • If you must use eth_getLogs, limit the block range to small windows (100-500 blocks) and retry on empty results.

eth_getTransactionReceipt Parse Errors

Symptoms:

  • Calls to eth_getTransactionReceipt return malformed or unparseable responses for certain transactions.
  • ethers.js or viem throw errors when processing receipts.
  • Contract deployment receipts fail to parse the contractAddress field.

Cause: The Cosmos EVM module's transaction receipt encoding can differ from standard Ethereum in edge cases, particularly for contract creation transactions and transactions involving precompile calls.

Solution:

  • For contract deployments, use computed addresses instead of relying on the receipt's contractAddress field:
import { ethers } from "ethers";

// For CREATE deployments: compute from sender + nonce
const deployerAddress = "0xYourDeployerAddress";
const nonce = await provider.getTransactionCount(deployerAddress);
const computedAddress = ethers.getCreateAddress({
from: deployerAddress,
nonce: nonce,
});

// For CREATE2 deployments: compute from factory + salt + initCodeHash
const computedAddress = ethers.getCreate2Address(
factoryAddress,
salt,
initCodeHash
);
  • For general receipt parsing, wrap receipt fetching in a try-catch and fall back to the RPC's raw response if the library parser fails:
try {
const receipt = await provider.getTransactionReceipt(txHash);
} catch (e) {
// Fall back to raw RPC call
const rawReceipt = await provider.send("eth_getTransactionReceipt", [txHash]);
// Parse manually
}

Balance Shows 0 in the Webapp

Symptoms:

  • The webapp shows a balance of 0 for all tokens.
  • The faucet confirms a successful drip, but the balance does not update.
  • MetaMask shows the correct balance, but the webapp does not.

Cause: The webapp's config.js has the wrong Chain ID configured. If chainConfig.chainId is set to the deprecated 47474 instead of 5446, the webapp connects to the wrong chain or fails to match the wallet's chain, resulting in zero balances.

Solution:

  1. Open config.js in the webapp source.
  2. Verify that chainConfig.chainId is 5446:
    export const chainConfig = {
    chainId: 5446, // NOT 47474
    // ...
    };
  3. Also verify chainIdHex is "0x1546".
  4. Rebuild and redeploy the webapp.
  5. If using a custom deployment, check that the RPC URL in config.js points to testnet.specterchain.com.

AutoCliOpts Panic in app.go

Symptoms: When starting the Specter node, it panics during initialization with an error referencing AutoCliOpts and address codec:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation]

goroutine 1 [running]:
github.com/cosmos/cosmos-sdk/server.AddCommands (...)
autocli.go:XX

Cause: The AutoCliOpts function in app.go is missing the address codec configuration. The Cosmos SDK's autocli module requires a properly initialized AddressCodec to encode and decode Bech32 addresses. If the codec is nil, it causes a nil pointer dereference at startup.

Solution: Ensure that the AutoCliOpts() method on the app struct returns a properly configured AddressCodec:

func (app *SpecterApp) AutoCliOpts() autocli.AppOptions {
modules := make(map[string]appmodule.AppModule, 0)
for _, m := range app.ModuleManager.Modules {
if moduleWithName, ok := m.(module.HasName); ok {
moduleName := moduleWithName.Name()
if appModule, ok := m.(appmodule.AppModule); ok {
modules[moduleName] = appModule
}
}
}

return autocli.AppOptions{
Modules: modules,
AddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

The key fix is including AddressCodec, ValidatorAddressCodec, and ConsensusAddressCodec in the returned AppOptions. Without these, any CLI command that formats addresses will panic.


General Debugging Tips

Verify Chain Connectivity

# Check if the RPC is responding
curl -s -X POST https://testnet.specterchain.com \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'

# Expected: {"jsonrpc":"2.0","id":1,"result":"0x1546"}

Check Contract Deployment

# Verify a contract exists at an address
curl -s -X POST https://testnet.specterchain.com \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_getCode","params":["0x908aA11Dc9F2e2C3F69892acaDE112e831c0a14a","latest"],"id":1}' \
| python3 -c "import sys,json; r=json.load(sys.stdin)['result']; print('Deployed' if len(r) > 2 else 'No code')"

Inspect a Transaction

# Get transaction details
curl -s -X POST https://testnet.specterchain.com \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0xYourTxHash"],"id":1}'

Check Nullifier Status

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://testnet.specterchain.com");
const nullifierRegistry = new ethers.Contract(
"0xaadb9c3394835B450023daA91Ad5a46beA6e43a1",
["function isSpent(bytes32 nullifier) view returns (bool)"],
provider
);

const spent = await nullifierRegistry.isSpent(nullifierHash);
console.log("Nullifier spent:", spent);

Verify Merkle Root

const commitmentTree = new ethers.Contract(
"0xE29DD14998f6FE8e7862571c883090d14FE29475",
["function getRoot() view returns (bytes32)"],
provider
);

const root = await commitmentTree.getRoot();
console.log("Current Merkle root:", root);