diff --git a/codex-rs/core/src/error.rs b/codex-rs/core/src/error.rs index 80d60619dd..439bda3330 100644 --- a/codex-rs/core/src/error.rs +++ b/codex-rs/core/src/error.rs @@ -460,6 +460,12 @@ impl std::fmt::Display for UsageLimitReachedError { "You've hit your usage limit.{}", retry_suffix(self.resets_at.as_ref()) ), + Some(PlanType::Unknown(plan)) + if plan.eq_ignore_ascii_case("self_serve_business_usage_based") => + { + "You've hit your usage limit. Contact your admin to add credits to continue." + .to_string() + } Some(PlanType::Unknown(_)) | None => format!( "You've hit your usage limit.{}", retry_suffix(self.resets_at.as_ref()) diff --git a/codex-rs/core/src/error_tests.rs b/codex-rs/core/src/error_tests.rs index 51cbf42dde..22a8ec564a 100644 --- a/codex-rs/core/src/error_tests.rs +++ b/codex-rs/core/src/error_tests.rs @@ -243,6 +243,26 @@ fn usage_limit_reached_error_formats_business_plan_without_reset() { ); } +#[test] +fn usage_limit_reached_error_formats_self_serve_business_usage_plan() { + let base = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap(); + let resets_at = base + ChronoDuration::hours(1); + with_now_override(base, move || { + let err = UsageLimitReachedError { + plan_type: Some(PlanType::Unknown( + "self_serve_business_usage_based".to_string(), + )), + resets_at: Some(resets_at), + rate_limits: Some(Box::new(rate_limit_snapshot())), + promo_message: None, + }; + assert_eq!( + err.to_string(), + "You've hit your usage limit. Contact your admin to add credits to continue." + ); + }); +} + #[test] fn usage_limit_reached_error_formats_default_for_other_plans() { let err = UsageLimitReachedError { diff --git a/docs/images/self-serve-business-usage-limit.png b/docs/images/self-serve-business-usage-limit.png new file mode 100644 index 0000000000..6c4b1d983f Binary files /dev/null and b/docs/images/self-serve-business-usage-limit.png differ