Repository navigation
fix(signals): Reduce inbox report failures via retries and relay fix - #57099
Merged
Merged
Conversation
~70% of signal report research runs have been failing because Modal sandbox agents crash before producing output. Three things compound: 1. The SSE relay in relay_sandbox_events.py didn't catch httpx.HTTPStatusError (404s from dead sandboxes), so it crashed immediately instead of marking the stream as errored. This left the workflow with no heartbeats and a silent 5-minute countdown to inactivity timeout. 2. Both select_repository_activity and run_agentic_report_activity used maximum_attempts=1, meaning any transient sandbox crash permanently killed the report with no retry. 3. When _drain_final_log raised its RuntimeError, the message said only "no agent message" with no hint of the actual cause (e.g. inactivity timeout, follow-up delivery failure), making debugging harder.
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
products/tasks/backend/temporal/process_task/activities/relay_sandbox_events.py:327-335
**Non-404 4xx errors treated as retryable**
The comment says "Retryable server errors (502, 503, etc.)" but the fallthrough also catches other permanent 4xx codes — e.g. `401 Unauthorized`, `403 Forbidden`, `410 Gone` — and retries them up to `MAX_RECONNECT_ATTEMPTS` times. None of those will recover on reconnect, so it would be cleaner to only retry on 5xx (or at least also `return` early for other 4xx codes the way 404 does).
### Issue 2 of 2
products/tasks/backend/temporal/process_task/activities/relay_sandbox_events.py:328-334
**Missing `error` field in non-404 HTTP error log**
The `httpx.ReadTimeout` and `httpx.TransportError` handlers both include `error=str(e)` in their structured log entries, but the new 5xx reconnect path omits it. Including the response body or status message would help distinguish e.g. a `502 Bad Gateway` from a `503 Service Unavailable` when diagnosing relay failures.
```suggestion
# Retryable server errors (502, 503, etc.)
reconnect_count += 1
logger.warning(
"relay_sandbox_events_http_error",
run_id=run_id,
status_code=e.response.status_code,
error=str(e),
reconnect_count=reconnect_count,
)
await asyncio.sleep(min(reconnect_count * 2, 10))
```
Reviews (1): Last reviewed commit: "fix(signals): reduce inbox report failur..." | Re-trigger Greptile |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Only retry on 5xx — all 4xx codes (401, 403, 404, 410, etc.) indicate the sandbox is gone or unreachable, so reconnecting won't help.
Contributor
|
⏭️ Skipped snapshot commit because branch advanced to The new commit will trigger its own snapshot update workflow. If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:
|
Contributor
Query snapshots: Backend query snapshots updatedChanges: 1 snapshots (1 modified, 0 added, 0 deleted) What this means:
Next steps:
|
sortafreel
approved these changes
Apr 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Users have been reporting that their Signals inbox goes empty shortly after enabling sources, and stays that way - showing "Inbox is warming up…". Others see reports briefly appear as "researching" then vanish with no retry. These reports fail, and one issue is we have been hiding these in the UI completely, which I'm fixing in PostHog/code#1950. But, there's the core issue of failures too.
Handing it over to Claude:
Investigation of production data over the last 7 days shows ~70% of signal report research runs are failing, with the failure rate climbing:
(Source:
signal_report_completedevents, grouped byproperties.result)Session replay signals are hit hardest — 3,693 failed vs 448 ready (89% failure rate) over the last 48h, compared to ~50% for error_tracking reports. 68 unique orgs are affected by failures vs only 9 getting ready reports.
The dominant error across all failures is a single
RuntimeError:(Seen on every error log from
temporal-worker-video-exportwithactivity_type=run_agentic_report_activity, e.g. report019ddb56-9b63-7e72-9430-368da7915f10for team 222600, report019ddb62-d0f6-7bd5-bd38-66f177caa64bfor team 61853)Three compounding issues cause this:
1. The SSE relay crashes on sandbox 404s instead of handling them
When a Modal sandbox dies, its
/eventsURL returns HTTP 404. The relay's reconnect loop inrelay_sandbox_events.pycatcheshttpx.TransportErrorandhttpx_sse.SSEError— buthttpx.HTTPStatusErroris a sibling class (inherits fromHTTPError, notTransportError), so 404s escape the reconnect loop entirely.This is confirmed by 2,333
HTTPStatusErroroccurrences in error tracking (issuec95785db) and production logs like:(From
temporal-worker-tasks-agent,activity_type=relay_sandbox_events, e.g. runa5256b26-4d64-45a8-be39-26af4805dbefat 2026-04-29T22:33)Once the relay crashes, the workflow loses its heartbeat source and the 5-minute inactivity timer starts counting down silently.
2. Zero retries on sandbox activitiesPer @sortafreel, keeping no retries for now to avoid a thundering herd, particularly till repo selection is stable via other changes.
Both
select_repository_activityandrun_agentic_report_activityuseRetryPolicy(maximum_attempts=1). Any transient sandbox failure — Modal container eviction, image build timeout (ExecutionError: Timed out waiting for image to be created, 102 occurrences in error tracking issuec3950dfd), OOM — permanently kills the report with no retry.3. Opaque error messages when sandbox runs fail
The
_drain_final_logRuntimeError says only "no agent message" with no hint of the underlying cause. TheTaskRun.error_messagefield (e.g."Run timed out due to inactivity","Follow-up delivery failed: ...") is available at the call site but not passed through, making triage harder than it needs to be.Changes
Handle
httpx.HTTPStatusErrorin the relay reconnect loop (relay_sandbox_events.py):Add retry policies to the two sandbox activities (summary.py):Per @sortafreel, keeping no retries for now to avoid a thundering herd, particularly till repo selection is stable via other changes.
select_repository_activity: 3 attempts, 10s initial backoff, 2x coefficient, 10min timeout per attempt (was 30min × 1 attempt)run_agentic_report_activity: 3 attempts, 30s initial backoff, 2x coefficient, 20min timeout per attempt (was 4h × 1 attempt)Surface the TaskRun cause in
_drain_final_log(custom_prompt_runner.py):"TaskRun reached terminal status=failed (cause: Run timed out due to inactivity) — no agent message"instead of just"no agent message"How did you test this code?
I'm an agent. I ran
ruff checkon all 3 changed files (all passed) and verified there are no import or type errors. The relay 404 fix was validated by tracing thehttpxclass hierarchy (HTTPStatusError→HTTPError;TransportError→RequestError→HTTPError), confirming the existing catch blocks don't cover it.The retry policy changes are to Temporal workflow configuration and don't have dedicated unit tests — they're verified by production behavior.
Publish to changelog?
No.
🤖 Agent context
signal_report_completedevents grouped byproperties.resultandproperties.source_products), searchedtemporal-worker-video-exportandtemporal-worker-tasks-agentlogs via the logs MCP tool, read the full process-task workflow/relay/sandbox code path, and correlated error tracking issues (c95785dbHTTPStatusError 2333 occ,c3950dfdExecutionError 102 occ,25a722fdRuntimeError 956 occ).447fa2b453con Apr 22 — that's not reverted here (policy decision for the Tasks team), but the relay fix and retries should significantly reduce failures under the current timeout.coderepo — separate PR.