anthropics / anthropics/claude-code
[BUG] Monitor tool: doesn't respect persistent flag and timeout_ms schema caps at 3600000 but actual lifetime is ~30 minutes, even during active (non-idle) sessions
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
### Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (related but distinct: #63023, #65968 — see below)
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
### What's Wrong?
The `Monitor` tool now hard-rejects persistent and `timeout_ms` above 3600000 (1 hour) even with persistent set, it rejects with a schema validation error, and even a Monitor started with the maximum now allowed (3600000) is reported as expiring after only ~30 minutes — during a continuously active session, not an idle or paused one. It goes against the docs: [](https://code.claude.com/docs/en/tools-reference#monitor-tool)
Calling `Monitor` with `timeout_ms: 86400000` (24 hours) fails immediately:
```
InputValidationError: [
{
"origin": "number",
"code": "too_big",
"maximum": 3600000,
"inclusive": true,
"path": ["timeout_ms"],
"message": "timeout_ms must be <= 3600000"
}
]
```
Retrying at the allowed maximum (`timeout_ms: 3600000`) succeeds, but the tool's own confirmation text says the monitor "expires in 30m," not 1h:
```
Monitor started (task , expires in 30m unless the source ends first; you get one notice at expiry — re-arm if you still need the watch)
```
This is distinct from #63023 / #65968 (background tasks reaped on session pause/idle-suspend): my session never went idle — it was actively processing `task-notification` events roughly every 30 minutes, generated by this same monitor's own repeated expiry, for several hours straight. Re-arming immediately after each expiry produces the same ~30-minute lifetime again, indefinitely, regardless of session/user activity.
### What Should Happen?
We should not have a limit on the monitor time, or bring back the old 24h limit....
Also either:
- The `timeout_ms` schema max should match the tool's actual honored lifetime (so a rejected value doesn't imply a longer-lived monitor is possible), and/or
- A `Monitor` started with any value up to the documented/allowed max should actually run for that long during active use, not silently cap out near 30 minutes.
At minimum the discrepancy between the accepted schema max (3600000) and the actual observed lifetime (~30 min) should not exist.
### Error Messages/Logs
```
InputValidationError: [
{
"origin": "number",
"code": "too_big",
"maximum": 3600000,
"inclusive": true,
"path": ["timeout_ms"],
"message": "timeout_ms must be <= 3600000"
}
]
```
```
Monitor started (task , expires in 30m unless the source ends first; you get one notice at expiry — re-arm if you still need the watch). You will be notified on each event. Keep working — do not poll or sleep. Events may arrive while you are waiting for the user — an event is not their reply.
```
```
[Monitor expired after 30m with no events delivered. Re-arm it if you still need the watch — and widen the filter if silence was unexpected.]
```
### Steps to Reproduce
1. Register a long-running `Monitor` intended to run for many hours (e.g. a persistent background poll loop), with `timeout_ms: 86400000`.
2. Observe the call fails with `InputValidationError: timeout_ms must be <= 3600000`.
3. Retry with `timeout_ms: 3600000` (the allowed maximum). The call succeeds, but the confirmation text says "expires in 30m."
4. Keep the session actively working (respond to normal messages, no idle period).
5. After ~30 minutes, receive a `task-notification` saying the monitor "expired after 30m with no events delivered," even though the underlying watched process (and the session) were both still alive/active.
6. Re-arm by calling `Monitor` again with the same command; the new monitor again expires after ~30 minutes, independent of user/session activity.
### Claude Model
Not sure / Multiple models
### Is this a regression?
I don't know
### Last Working Version
### Claude Code Version
2.1.270 (Claude Code)
### Platform
Anthropic API
### Operating System
Ubuntu/Debian Linux
### Terminal/Shell
Non-interactive/CI environment
### Additional Information
Related but distinct issues already open on this repo:
- #63023 — "Background agents silently die on session pause/resume" (framed around session pause/idle-suspend; I added a comment there with a shorter version of this data before realizing the mechanism differs)
- #65968 — closed as a duplicate of #63023, also framed around "idle/suspend boundaries"
Both of those describe reaping tied to session inactivity. This report is specifically about (a) a schema-level cap change that rejects previously-documented-as-valid `timeout_ms` values outright, and (b) the same ~30-minute cap applying even when the session is continuously active with no idle period — which doesn't fit the "idle/suspend" framing of the related issues, so I'm filing it separately in case the root cause differs (e.g. an unconditional per-monitor lifetime cap vs. an idle-detection reaper).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the Monitor tool entry point, focusing on the timeout_ms schema and the expiry behavior described in the report. Reproduce the 86400000 rejection and the roughly 30-minute expiry with 3600000 during an active session; done means the documented and observed limits agree.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100