BigPizzaV3/CodexPlusPlus · error · anyhow::Error

启动超时必须是正数:

Error message

启动超时必须是正数:{timeout}

What it means

build_mcp_toml_body validates the MCP form's startup_timeout_sec field. If the field is non-empty, it is parsed as f64; if the value parses but is zero, negative, NaN or infinite, this bail fires. The library requires startup timeout to be a strictly positive finite number because it is written verbatim into the codex config.toml and a non-positive timeout would be rejected or misbehave at runtime.

Solutions

  1. Set startup_timeout_sec to a positive number greater than 0 (e.g. 30).
  2. If the timeout is unknown, leave the field empty/omitted so the default is used instead of 0.
  3. Trim whitespace and ensure no sign character or scientific notation that evaluates to <= 0 is present.
  4. If importing JSON, fix the offending server's startup_timeout_sec before import, or accept the per-entry warning and correct it afterwards.

Example fix

// before
startup_timeout_sec = 0
// after
startup_timeout_sec = 30
Defensive patterns

Strategy: validation

Validate before calling

fn valid_timeout(s: &str) -> bool {
    match s.trim().parse::<f64>() {
        Ok(v) => v.is_finite() && v > 0.0,
        Err(_) => false,
    }
}

Try / catch

match build_mcp_toml_body(&form) {
    Ok(body) => /* ... */,
    Err(e) if e.to_string().contains("启动超时") => show_field_error("startup_timeout_sec", format!("{e}")),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling build_mcp_toml_body (directly or via parse_mcp_servers_json) with a form whose startup_timeout_sec is e.g. "0", "-5", "0.0", or a value that parses to NaN/inf (the parse itself failing produces the separate '必须是数字' error).

Common situations: User types 0 or a negative number into the startup-timeout field of the MCP config UI; JSON import carries startup_timeout_sec: 0 copied from another tool; locale/formatter output like "1,5" would hit the sibling numeric error, but "-1" hits this one.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/48d9daf0c91d040f. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/mcp_config.rs:217

                table["args"] = Item::Value(TomlValue::Array(array));
            }
            set_string(table, "cwd", &form.cwd);
            set_inline_map(table, "env", &form.env);
        }
        McpTransport::Http => {
            set_string(table, "url", &form.url);
            set_inline_map(table, "http_headers", &form.http_headers);
            set_string(table, "bearer_token", &form.bearer_token);
        }
    }

    let timeout = form.startup_timeout_sec.trim();
    if !timeout.is_empty() {
        let parsed: f64 = timeout
            .parse()
            .with_context(|| format!("启动超时必须是数字:{timeout}"))?;
        if !parsed.is_finite() || parsed <= 0.0 {
            anyhow::bail!("启动超时必须是正数:{timeout}");
        }
        // 整数写成整数:toml_edit::value(30.0) 会产出 `30.0`,
        // 而 codex 那边期望 f64,两种都收,但配置文件里 `30` 更干净。
        if parsed.fract() == 0.0 && parsed.abs() < 1e15 {
            table["startup_timeout_sec"] = toml_edit::value(parsed as i64);
        } else {
            table["startup_timeout_sec"] = toml_edit::value(parsed);
        }
    }

    // enabled = true 是默认值,不写进去省得每条都带一行噪音
    if !form.enabled {
        table["enabled"] = toml_edit::value(false);
    }

    if !form.extra_toml.trim().is_empty() {
        let extra: DocumentMut = form
            .extra_toml

View on GitHub (pinned to b1ed92e5e4)