Fix: ElizaOS Solana Agent Kit Public Key Not Found Error
If your ElizaOS framework crashes during initialization with the Solana Public Key not found in settings error, the runtime engine has failed to derive a valid execution identity.
Diagnostic Implementation Block
To fix this immediately, you must convert your Solana JSON keypair array into a Base58 string compatible with the ElizaOS .env parser.
# Convert your Solana JSON keypair to Base58 using the Solana CLI
solana-keygen pubkey prompt://
# Inside your .env file, provide the resulting Base58 string
SOLANA_PRIVATE_KEY=3KkpX... (Your Base58 Secret Key)
SOLANA_PUBLIC_KEY=YourPublicAddress...
Fix: Ensure the .env variables are correctly passed to your Docker container. If you recently debugged an elizaos failed to parse json from response openai grammar error, remember that environment variable parsers are equally unforgiving regarding unexpected JSON arrays in shell environments.
Architectural Context: Solana Keypair Parsing and Uint8Array
The Solana blockchain utilizes the Ed25519 elliptic curve for cryptographic signatures. Ed25519 is a Edwards-curve Digital Signature Algorithm (EdDSA) that offers high performance and high security without the pitfalls of older ECDSA curves like secp256k1. By default, the Solana CLI generates keypair files (typically id.json) as a raw JSON array of 64 integers. This is a serialized representation of a Uint8Array. The first 32 bytes constitute the secret seed, and the subsequent 32 bytes represent the public key cached for performance.
When the ElizaOS Solana Agent Kit boots, it relies on the @solana/web3.js library and underlying cryptographic primitives like tweetnacl. The plugin looks for the SOLANA_PRIVATE_KEY environment variable. If an operator accidentally pastes the raw JSON array (e.g., [12, 45, 233...]) into the .env file, the Node.js runtime (via process.env) evaluates it as a literal string. The ElizaOS plugin initialization logic usually attempts to pass this string directly to Keypair.fromSecretKey() or a similar utility. However, Keypair.fromSecretKey() expects a Uint8Array of 64 bytes, not a string representation of an array.
If the framework attempts to decode the string as Base58 (using the bs58 library), the operation fails immediately. Base58 is a specific encoding scheme used by Solana to provide a human-readable format that avoids ambiguous characters (like 0, O, I, l). Because a JSON bracket [ or a comma , are not valid characters in the Base58 alphabet, the decoder throws an exception. The derivation function then returns null or undefined, leading to the “Public Key not found” error because the primary signing artifact is structurally malformed. This failure is a low-level cryptographic rejection, far removed from the higher-level elizaos failed to parse json from response openai grammar error that users often encounter later in the agent’s lifecycle.
Deep Dive: Docker Container Asset Routing and Permission Faults
In containerized deployments (Docker/Kubernetes), the error often stems from “Environment Variable Leakage” or “Mount Point Desynchronization.” If you are using the SOLANA_KEYPAIR_PATH variable instead of the raw secret key string, the Node.js process must have visibility into the container’s filesystem.
- Volume Mount Mismatches: If your
docker-compose.ymlmounts the keypair at/etc/solana/id.jsonbut your ElizaOS config points to/app/id.json, thefs.readFileSync()call inside the agent will return an empty buffer or throw anENOENTerror. Because most AI agent frameworks utilize a “Silent Fallback” pattern to avoid crashing during startup, they may simply log a warning and proceed with an empty public key, only to crash later when the first transaction signature is requested. - Stringified JSON in Shells: Many CI/CD pipelines (GitHub Actions, GitLab CI) struggle with JSON arrays in environment variables. If the array is not properly escaped, the shell may interpret the brackets as globbing patterns or sub-shell executions. This results in a “mangled” string being passed to ElizaOS, which will never pass the
bs58.decode()validation check. - The Uint8Array vs. SecretKey Distinction: A common technical misconception is that the 64-byte array in
id.jsonis “the private key.” In Ed25519, the secret key is actually only the first 32 bytes (the seed). The full 64-byte array is the concatenation of[seed, public_key]. If you manually try to construct aKeypairusing only the first 32 bytes without specifying the correct constructor,web3.jsmay reject the input as “Invalid length,” further complicating the “Public Key not found” diagnostic loop.
Preventative Maintenance: Production-Grade Configuration Manual
To immunize your automated trading or AI-agent infrastructure against derivation panics, implement a strict configuration schema and pre-flight validation layer.
1. Environment Variable Schema (Standardized)
- Preferred Format: Always use the Base58 encoded secret key in
.envfiles. This eliminates the need for JSON parsing and reduces the payload size. - Variable Naming: Use
SOLANA_PRIVATE_KEYfor the Base58 string andSOLANA_PUBLIC_KEYfor the address. While the public key can be derived from the private key, providing it explicitly allows the agent to perform a “sanity check” (deriving the pubkey from the privkey and comparing it to the provided address) before attempting transactions.
2. Automated Key Derivation Interceptors
Inject a TypeScript pre-flight hook into your agent’s entry point (e.g., index.ts or main.ts). This script should normalize the environment variables before the ElizaOS framework initializes:
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
/**
* ElizaOS Pre-Flight Hook: Keypair Sanitization
*/
function sanitizeSolanaEnv(): void {
const rawKey = process.env.SOLANA_PRIVATE_KEY;
if (!rawKey) return;
try {
// Case 1: Raw JSON Array detected
if (rawKey.trim().startsWith('[')) {
const secretArray = JSON.parse(rawKey);
const keypair = Keypair.fromSecretKey(Uint8Array.from(secretArray));
process.env.SOLANA_PRIVATE_KEY = bs58.encode(keypair.secretKey);
console.log('✅ Sanitized SOLANA_PRIVATE_KEY from JSON to Base58');
}
// Case 2: Validation Check
const decoded = bs58.decode(process.env.SOLANA_PRIVATE_KEY!);
if (decoded.length !== 64) {
throw new Error(`Invalid Key Length: Expected 64 bytes, got ${decoded.length}`);
}
} catch (error) {
console.error('❌ CRITICAL: SOLANA_PRIVATE_KEY is malformed.');
process.exit(1); // Fail fast in production
}
}
3. Corporate Security Policy for Agent Identity
- Secret Management: Never commit
.envfiles to git. Use a Secrets Manager (AWS Secrets Manager, HashiCorp Vault) to inject the Base58 string into the container at runtime. - Least Privilege: Ensure the Solana account associated with the agent only holds the minimum required SOL/USDC for its current epoch. This mitigates the impact of a key compromise due to environment variable exposure.
Advanced FAQ Layer
Q1: Why does ElizaOS need the Public Key at all if I provide the Private Key?
While the public key is mathematically derivable from the private key seed using the Ed25519 curve multiplication, the ElizaOS Solana Agent Kit often uses the public key for “Read-Only” initialization tasks, such as subscribing to account change listeners via WebSocket (RPC). By requiring the public key in settings, the framework can initialize these listeners immediately without waiting for the cryptographic engine to “warm up” and perform the derivation.
Q2: Can I use a BIP-39 mnemonic phrase directly in ElizaOS?
Most versions of the ElizaOS Solana plugin do not natively support BIP-39 mnemonics in the .env file due to the security risks associated with storing plain-text mnemonics. If you have a mnemonic, you should use a utility script (using @solana/web3.js and ed25519-hd-key) to derive the 0th account (derivation path m/44'/501'/0'/0') and then export that specific private key as a Base58 string for ElizaOS.
Q3: How do I handle ‘Custom RPC’ public key errors?
Sometimes the error “Public Key not found” is a red herring for “RPC Node unreachable.” If the agent kit attempts to verify the public key by querying its balance on-chain and the RPC call fails (due to a rate limit or invalid URL), the plugin may catch the generic error and incorrectly report that the public key is missing. Always verify your SOLANA_RPC_URL availability using curl before debugging the keypair format.