xai-org/grok-build · error

set_client_name called more than once

Error message

set_client_name called more than once

What it means

set_client_name stores the process-level fallback ClientType (used for the User-Agent origin) in a OnceCell and .expect()s the set succeeds, so a second call in the same process panics with 'set_client_name called more than once'. The value is intentionally write-once per process.

Source

Thrown at crates/codegen/xai-grok-http/src/lib.rs:177

                self.origin.product,
                self.agent_product,
                self.agent_version,
                self.platform.os,
                self.platform.arch,
            ),
        }
    }
}

fn agent_version() -> String {
    xai_grok_version::VERSION.to_string()
}

/// Set the process-level fallback origin client type for `User-Agent`.
pub fn set_client_name(client_type: ClientType) {
    CLIENT_TYPE
        .set(client_type)
        .expect("set_client_name called more than once");
}

pub fn process_user_agent_string() -> String {
    let agent_version = agent_version();
    let origin = origin_client_info_from_env().unwrap_or_else(|| {
        origin_client_info_from_client_type(
            CLIENT_TYPE.get().copied().unwrap_or(ClientType::Generic),
            Some(agent_version.clone()),
        )
    });

    UserAgent {
        origin,
        agent_product: "grok-shell",
        agent_version,
        platform: PlatformInfo::current(),
    }
    .render()

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Call set_client_name exactly once, as early as possible in main()
  2. Guard the call with std::sync::Once so repeats are no-ops
  3. In tests, run each set_client_name caller in its own test process or avoid calling it in unit tests
  4. If the value must change, use a library-level API that supports replacement instead of the process-global setter

Example fix

// before
set_client_name(ClientType::Cli);
// later, possibly again
set_client_name(ClientType::Cli); // panics
// after
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| set_client_name(ClientType::Cli));
Defensive patterns

Strategy: validation

Validate before calling

use std::sync::Once;
static CLIENT_NAME_INIT: Once = Once::new();
CLIENT_NAME_INIT.call_once(|| xai_grok_http::set_client_name(client_type));

Type guard

null

Try / catch

null // the panic fires on a programming error; guard the call instead of catching it

Prevention

When it happens

Trigger: Calling xai_grok_http::set_client_name twice - e.g. an init path and a fallback init path both running, tests calling it in each test without process isolation, or two libraries in one binary both initializing the client type.

Common situations: Unit tests in the same test binary (shared process) each calling set_client_name; CLI subcommand dispatch initializing twice; a lib and the embedding app both setting the origin client type.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/7f9bfa1fc47da6ef. Report an issue: GitHub.