{"record":{"id":"1c51fce957320795","repo":"BigPizzaV3/CodexPlusPlus","slug":"label-0","errorCode":null,"errorMessage":"{label}必须大于 0","messagePattern":"(.+?)必须大于 0","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/relay_config.rs","lineNumber":1544,"sourceCode":"fn validate_auth_json(auth_bytes: &[u8], path: &Path) -> anyhow::Result<()> {\n    if auth_bytes.iter().all(|byte| byte.is_ascii_whitespace()) {\n        return Ok(());\n    }\n    serde_json::from_slice::<Value>(auth_bytes)\n        .with_context(|| format!(\"{} 不是有效 JSON\", path.display()))?;\n    Ok(())\n}\n\nfn parse_optional_positive_u64(value: &str, label: &str) -> anyhow::Result<Option<u64>> {\n    let trimmed = value.trim();\n    if trimmed.is_empty() {\n        return Ok(None);\n    }\n    let parsed = trimmed\n        .parse::<u64>()\n        .with_context(|| format!(\"{label}必须是正整数\"))?;\n    if parsed == 0 {\n        anyhow::bail!(\"{label}必须大于 0\");\n    }\n    Ok(Some(parsed))\n}\n\nfn apply_context_limits_to_config(\n    config_text: &str,\n    context_window: &str,\n    auto_compact_limit: &str,\n) -> anyhow::Result<String> {\n    let mut doc = parse_toml_document(config_text)?;\n    if let Some(value) = parse_optional_positive_u64(context_window, \"上下文大小\")? {\n        doc[\"model_context_window\"] = toml_edit::value(value as i64);\n    }\n    if let Some(value) = parse_optional_positive_u64(auto_compact_limit, \"压缩上下文大小\")? {\n        doc[\"model_auto_compact_token_limit\"] = toml_edit::value(value as i64);\n    }\n    Ok(normalize_optional_toml(doc))\n}","sourceCodeStart":1526,"sourceCodeEnd":1562,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/relay_config.rs#L1526-L1562","documentation":"parse_optional_positive_u64 解析 profile 的上下文窗口 / 自动压缩阈值字符串：空串返回 None（表示不写入），非数字走「必须是正整数」错误，解析成功但值为 0 时走本错误「{label}必须大于 0」。label 是「上下文大小」或「压缩上下文大小」。结果最终写入 config.toml 的 model_context_window / model_auto_compact_token_limit。","triggerScenarios":"调用链 apply_relay_profile_to_home_* -> apply_context_limits_to_config 时，context_window 或 auto_compact_limit 传了 \"0\"（或 \"00\" 等解析为 0 的串）。留空不会触发；非数字触发的是另一条消息。","commonSituations":"用户想表达「不限制上下文」填 0（本实现里 0 非法，应留空）；UI 数字输入框默认值 0 被原样提交；从旧配置迁移时把 0 语义带了过来。","solutions":["想关闭限制就把对应输入留空（空 = 不写入该键）","填 ≥1 的正整数（如 128000）","UI 层用 min=1 的数字输入，把 0 视为空提交"],"exampleFix":"# before (profile settings)\ncontext_window = \"0\"\nauto_compact_limit = \"\"\n\n# after\ncontext_window = \"128000\"\nauto_compact_limit = \"\"   # 留空 = 不写入 model_auto_compact_token_limit","handlingStrategy":"validation","validationCode":"fn normalize_positive_u64_field(value: &str) -> String {\n    let t = value.trim();\n    if t.parse::<u64>().map(|v| v == 0).unwrap_or(false) {\n        String::new() // 把 0 规范化为空 = 不限制\n    } else {\n        t.to_string()\n    }\n}\n// 提交 profile 前对 context_window / auto_compact_limit 做该规范化","typeGuard":null,"tryCatchPattern":"if let Err(err) = apply_relay_profile_to_home_with_switch_rules_and_computer_use_guard(&home, &profile, &common, guard) {\n    if err.to_string().contains(\"必须大于 0\") {\n        // 提示：0 无效，留空表示不限制\n    } else { return Err(err); }\n}","preventionTips":["数字输入框设置 min=1，0 视为空提交","「不限制」语义统一用留空表达，不用 0","区分两条消息：非数字走「必须是正整数」，0 走本错误"],"tags":["context-window","numeric","validation","codex-plus-core"],"backgroundTag":"invalid-numeric-value","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}