You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
run_end_ceiling_ms falls back to the default for CLI-compatible 1e6 values #1359
run_end_ceiling_ms() says it reads CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS "as the CLI will see it" and notes that the CLI also reads spellings such as 1e6.
The current implementation uses int(raw), so 1e6 is treated as invalid and silently falls back to the SDK default of 600_000 ms instead of 1_000_000 ms.
This value drives the Python SDK's own between-turn ceiling while it waits for the CLI's session_state_changed: idle after a result. If the SDK and CLI parse the same environment value differently, the SDK may close stdin earlier or later than the caller configured.
Expected behavior
Either:
parse the same non-negative millisecond spellings that the CLI accepts, at least integral scientific notation such as 1e6; or
narrow the docstring/tests so the SDK explicitly accepts only plain integer strings.
I think option 1 better matches the current docstring and the intent of reading the value as the CLI will see it.
Possible fix
Use a finite non-negative numeric parser that preserves the current behavior for:
default / unset values;
0 meaning no limit;
whitespace around plain integers;
invalid strings falling back to the default;
negative values falling back to the default;
very large integer strings being honored and later clamped by the sleeper.
A regression test could add "1e6" -> 1_000_000 to TestRunEndCeilingFromEnv.test_parse.
Kept int() as the first attempt and only fall back to a float read when it fails, so the behaviours you listed as needing to survive do so by construction rather than by my re-deriving them: whitespace, 0, negatives, and the integer beyond float range, which keeps its exact value and is clamped later by the sleeper instead of turning into an infinity in the parser. inf and nan fall back to the default.
Your six cases are in TestRunEndCeilingFromEnv.test_parse. Two fail on main, 1e6 and 1e2; the other four pass either way and are there as controls.
One thing the issue leaves open and I had to pick: 1.5 now truncates to 1 rather than falling back to the default. Milliseconds are integral and truncation is what a float ceiling means downstream, but if you would rather a non-integral value stay a fallback, that is a one-line change and I will make it.
Activity
v0ropaev commentedon Oct 7, 2026
Opened #1370 for this, option 1.
Kept
int()as the first attempt and only fall back to a float read when it fails, so the behaviours you listed as needing to survive do so by construction rather than by my re-deriving them: whitespace,0, negatives, and the integer beyond float range, which keeps its exact value and is clamped later by the sleeper instead of turning into an infinity in the parser.infandnanfall back to the default.Your six cases are in
TestRunEndCeilingFromEnv.test_parse. Two fail on main,1e6and1e2; the other four pass either way and are there as controls.One thing the issue leaves open and I had to pick:
1.5now truncates to 1 rather than falling back to the default. Milliseconds are integral and truncation is what a float ceiling means downstream, but if you would rather a non-integral value stay a fallback, that is a one-line change and I will make it.