xai-org/x-algorithm · error · std::invalid_argument
XAI_ASYNC_EMB_TIMEOUT_SECONDS must be a positive integer
Error message
XAI_ASYNC_EMB_TIMEOUT_SECONDS must be a positive integer
What it means
XAI_ASYNC_EMB_TIMEOUT_SECONDS is parsed with strtol and must be a strictly positive integer with no trailing characters. If it is unset the code falls back to a 1800-second watchdog, so this error only fires when the variable exists but is malformed (empty, zero, negative, fractional, or containing non-numeric suffixes).
Source
Thrown at phoenix/xrex/cuda/async_emb/src/async_emb_comm.cc:68
void requireEnvironment(const char* name, const char* expected) {
const char* value = std::getenv(name);
if (value == nullptr || std::strcmp(value, expected) != 0) {
throw std::runtime_error(
"async_emb requires " + std::string(name) + "=" + expected + " before process startup"
);
}
}
std::chrono::seconds watchdogTimeout() {
const char* value = std::getenv("XAI_ASYNC_EMB_TIMEOUT_SECONDS");
if (value == nullptr) {
return std::chrono::seconds(1800);
}
char* end = nullptr;
long seconds = std::strtol(value, &end, 10);
if (end == value || *end != '\0' || seconds <= 0) {
throw std::invalid_argument("XAI_ASYNC_EMB_TIMEOUT_SECONDS must be a positive integer");
}
return std::chrono::seconds(seconds);
}
std::once_flag warmup_once;
void warmupKernels(int8_t* scratch, cudaStream_t stream) {
auto* bf16 = reinterpret_cast<__nv_bfloat16*>(scratch);
auto* f32 = reinterpret_cast<float*>(scratch);
auto* i32 = reinterpret_cast<int32_t*>(scratch);
const SliceLayout slices{0, 8, 1};
launch_lookup_dispatch(i32, bf16, bf16, slices, 1, stream);
launch_grad_dispatch(bf16, bf16, slices, stream);
launch_grad_segment_sum(bf16, i32, f32, f32, slices, 0, stream);
launch_lookup_combine(bf16, bf16, slices, stream);
XAI_CUDA_CHECK(cudaStreamSynchronize(stream));
}
View on GitHub (pinned to 24c60942c5)
Solutions
- Export a plain positive integer: export XAI_ASYNC_EMB_TIMEOUT_SECONDS=1800.
- Remove quotes/units/whitespace from the value in your job spec or .env file.
- If you do not need a custom timeout, unset the variable to use the 1800s default.
Example fix
# before export XAI_ASYNC_EMB_TIMEOUT_SECONDS="30m" # after export XAI_ASYNC_EMB_TIMEOUT_SECONDS=1800
Defensive patterns
Strategy: validation
Validate before calling
const char* v = std::getenv("XAI_ASYNC_EMB_TIMEOUT_SECONDS");
if (v) {
char* end = nullptr;
long n = std::strtol(v, &end, 10);
if (end == v || *end != '\0' || n <= 0)
throw std::runtime_error("XAI_ASYNC_EMB_TIMEOUT_SECONDS must be a positive integer");
} Prevention
- Use plain integers, no units or quotes, in env files.
- Add a config lint step that regex-validates ^[1-9][0-9]*$ for this variable.
When it happens
Trigger: Setting XAI_ASYNC_EMB_TIMEOUT_SECONDS to values like "", "0", "-5", "30s", "1.5", or "1800 " while constructing AsyncEmbContext (watchdogTimeout is called from the constructor).
Common situations: Kubernetes manifests quoting the value ("1800" is fine but "30s" from a duration convention is not), CI templates appending units, copy-paste from docs of a different timeout variable that accepts durations.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- async_emb: ${label} timed out waiting for step ${step}
- async_emb requires ${name}=${expected} before process startu
- async_emb received an invalid rank or world size
- async_emb received an invalid NCCL bootstrap payload
- type checking expression %s failed: invalid argument type: %
AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28).
Data as JSON: /api/errors/45466dc602dadd21.
Report an issue: GitHub.