{"record":{"id":"d0a33624656f3dc5","repo":"BigPizzaV3/CodexPlusPlus","slug":"sub2api-key-billing","errorCode":null,"errorMessage":"倍率接口返回结构不是 sub2api.key_billing","messagePattern":"倍率接口返回结构不是 sub2api\\.key_billing","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/sub2api.rs","lineNumber":108,"sourceCode":"    let cleaned = base_url.trim().trim_end_matches('/');\n    if cleaned.is_empty() {\n        return String::new();\n    }\n    if cleaned.ends_with(\"/sub2api/billing\") {\n        return cleaned.to_string();\n    }\n    if crate::protocol_proxy::has_version_suffix(cleaned) {\n        return format!(\"{cleaned}/sub2api/billing\");\n    }\n    format!(\"{cleaned}/v1/sub2api/billing\")\n}\n\nfn validate_sub2api_billing_response(response: &Sub2ApiBillingResponse) -> anyhow::Result<()> {\n    if response.object != \"sub2api.key_billing\"\n        || response.schema_version != 1\n        || response.billing_scope != \"token\"\n    {\n        anyhow::bail!(\"倍率接口返回结构不是 sub2api.key_billing\");\n    }\n    for value in [\n        response.group_rate_multiplier,\n        response.resolved_rate_multiplier,\n        response.effective_rate_multiplier,\n    ] {\n        if !value.is_finite() || value < 0.0 {\n            anyhow::bail!(\"倍率接口返回了无效倍率\");\n        }\n    }\n    if let Some(value) = response.user_rate_multiplier {\n        if !value.is_finite() || value < 0.0 {\n            anyhow::bail!(\"倍率接口返回了无效用户倍率\");\n        }\n    }\n    if response.observed_at.trim().is_empty() {\n        anyhow::bail!(\"倍率接口缺少观测时间\");\n    }","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/sub2api.rs#L90-L126","documentation":"Thrown by validate_sub2api_billing_response when the parsed response's envelope fields do not identify it as a sub2api token-scoped key_billing document: object != \"sub2api.key_billing\", schema_version != 1, or billing_scope != \"token\". The offending input is the JSON returned by the billing endpoint — it is structurally something else, so all multiplier fields are untrustworthy.","triggerScenarios":"Thrown at crates/codex-plus-core/src/sub2api.rs:108 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["确认上游 sub2api 版本兼容该 schema","检查端点 URL 是否指向了其他接口"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}