@@ -341,16 +341,32 @@ def set_model(self, model: str) -> None:
341341 means any provider/model the gateway has auth for can be requested.
342342 """
343343 log .info ("set openclaw model: %s (and clearing allowlist)" , model )
344- self . check_exec (
344+ set_cmd = (
345345 "openclaw config set agents.defaults.model.primary "
346- f"{ shlex .quote (model )} && "
347- # Reset allowlist to a single-entry list containing only the
348- # primary; we then immediately unset to remove the gating.
349- # `config unset` removes the key entirely so OpenClaw treats it
350- # as "no allowlist" -> all configured providers allowed.
351- "openclaw config unset agents.defaults.models 2>/dev/null || true" ,
352- timeout_s = 15 ,
346+ f"{ shlex .quote (model )} "
353347 )
348+ unset_cmd = "openclaw config unset agents.defaults.models 2>/dev/null || true"
349+
350+ # OpenClaw can emit startup/config warnings before returning from
351+ # `config set`, which occasionally takes longer than our old 15s budget.
352+ # Retry with a set-only path so stale plugin warnings do not kill pool
353+ # replenish for an otherwise healthy sandbox.
354+ try :
355+ self .check_exec (f"{ set_cmd } && { unset_cmd } " , timeout_s = 30 )
356+ return
357+ except SandboxError as first_error :
358+ log .warning (
359+ "openclaw config set+unset failed once; retrying set-only path: %s" ,
360+ _short (str (first_error ), 300 ),
361+ )
362+
363+ self .check_exec (set_cmd , timeout_s = 45 )
364+ unset_res = self .exec (unset_cmd , timeout_s = 20 )
365+ if not unset_res .ok ():
366+ log .warning (
367+ "openclaw config unset allowlist failed (non-fatal): %s" ,
368+ _short (unset_res .stderr or unset_res .stdout , 240 ),
369+ )
354370
355371 def start_gateway (self , * , poll_iters : int = 80 , poll_interval_s : float = 0.25 ) -> None :
356372 """Start the local OpenClaw gateway and poll until it answers HTTP."""
0 commit comments