Skip to content

fix(worker): a returned 5xx marks the worker's server span as an error - #1406

Merged
AutomatosAI merged 2 commits into
mainfrom
fix/1310-worker-5xx-span-error
Nov 4, 2026
Merged

AutomatosAI merged 2 commits into
mainfrom
fix/1310-worker-5xx-span-error

Conversation

@daarthur

@daarthur daarthur commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

Closes #1310.

The problem. The workspace worker's server span (_traced in services/workspace-worker/worker_otel.py) was marked ERROR only when a handler raised. The canvas routes (worker_routes_canvas.py) return their failures as a 500 instead of raising. So a failed canvas start, approval or stop left its span UNSET, with only http.status_code set. Tempo's error-rate queries and "traces with errors" filters missed those failures.

The fix. A new _answered runs after the app answers:

  • A 5xx sets error.type = the status code and Status(ERROR, "<status>"). That's how OpenTelemetry's HTTP semantic conventions mark a failed server span. The description equals the error.type, as the worker's _failed does. The API's export rule (_failed_type in core/observability/otel.py) keeps a description only when it equals the error.type.
  • No message text goes on the span, so API traces: query values can leave in exception messages and span status (PRD-256 Principle 5) #1107's type-only rule holds.
  • A 4xx is the caller's error and stays UNSET, as before.
  • A raised exception is handled as before: _failed records its type and re-raises.

How it was verified

  • New test in orchestrator/tests/test_prd256_o2b_worker_span.py. Routes that return 500 and 503 give an ERROR span with error.type set to the code. Routes that return 404 and 409 stay UNSET with no error.type. A path in the response body never reaches the span.

  • It fails without the fix: with worker_otel.py stashed, StatusCode.UNSET != StatusCode.ERROR.

  • Review: a subagent review found no bugs. It flagged one nit, the description format, now matched to the API's rule.

  • Local runs (Python 3.11 venv from orchestrator/requirements.lock + requirements-dev.lock):

    • pytest tests/test_prd256_o2b_worker_span.py tests/test_prd256_o5_logs_metrics.py: 19 passed.
    • ruff check on both files: clean.
    • scripts/ci/check_changed_code_shape.py: 0 errors.
  • Tests added or updated, and they fail without this change

  • CI green (a lane marked non-required counts too)

  • Both editions considered: local (AUTH_EDITION=local) and hosted. It's the worker's tracing, the same code in both.

  • UI change: screenshots below (none)

AI assistance

  • None
  • Assisted: tool(s): Claude Code (Claude Opus 5.5); it wrote or changed: the fix and the test, from the issue's own spec
  • I have read and understood every line of this change, and can explain it in review

Checklist (AGENTS.md)

  • Every commit signed off (git commit -s)
  • No secrets, customer data or credentials anywhere in the change
  • Settings through orchestrator/config.py; no hardcoded values (none added)
  • Replaced paths deleted in this pull request (no shims or V2 copies)
  • Migration (if any): none
  • New routes the frontend calls are in orchestrator/reports/route-manifest.json (none)
  • Docs updated where behaviour changed (the middleware's docstring)

🤖 Generated with Claude Code

The worker's server span (_traced) was marked ERROR only when a handler
raised. The canvas routes return their failures as a 500 rather than
raising, so a failed canvas start, approval or stop left the span UNSET
with only http.status_code, and Tempo's error filters missed it.

After the app answers, a 5xx now sets Status(ERROR, "HTTP <status>") and
error.type to the status code, as OpenTelemetry's HTTP conventions mark
a server span. No message text goes on the span, so #1107's type-only
rule holds. A 4xx is the caller's and stays UNSET.

Closes #1310

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Dave Arthur <davidarthur@hotmail.com>
@daarthur
daarthur requested a review from AutomatosAI as a code owner November 1, 2026 23:44

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2c1ed8b8-6389-45b3-a4c4-a98890bc2552
Commits

Reviewing files that changed from the base of the PR and between c2fba3b and 08bcd1b.

Files selected for processing: 2
  • orchestrator/tests/test_prd256_o2b_worker_span.py
  • services/workspace-worker/worker_otel.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The worker tracing middleware now marks returned responses with status codes of 500 or higher as span errors. Tests cover 500, 503, 404, and 409 responses, including checks that secret error text is absent from span descriptions and attributes.

Changes: Worker response tracing

Layer / File(s) Summary
Record and test response status
services/workspace-worker/worker_otel.py, orchestrator/tests/test_prd256_o2b_worker_span.py
_answered records the response status and marks 5xx spans as errors with a status-based description and error.type. The tracing middleware uses this helper. Tests check 5xx and 4xx span behavior and verify that secret response text is not recorded.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

Suggested reviewers: automatosai

Merge Risk: Minimal · up to 08bcd

Returned 5xx responses are intended to be marked as errors without exposing response text. No merge-blocking risk was identified.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title names the main change: a returned 5xx response now marks the workspace worker's server span as an error. It matches the raw summary (_answered marks status codes of 500 or higher as ERROR) a…
Linked Issues check Passed Issue [#1310] requires returned 5xx responses to mark the worker server span as ERROR, set error.type to the status code, and avoid message text. It also requires returned 4xx responses to remain UN…
Out of Scope Changes check Passed The changed files are limited to the worker tracing implementation and its focused span test. The documentation update explains the changed middleware behavior. The test additions support issue [#1310…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Description check Passed The description follows the repository template closely: it has a 'What and why' section that links issue #1310 and explains the problem and fix, and a 'How it was verified' section with a named test …
Full details: Title check

Explanation

The title names the main change: a returned 5xx response now marks the workspace worker's server span as an error. It matches the raw summary (_answered marks status codes of 500 or higher as ERROR) and the linked issue #1310. The 'fix(worker)' prefix is a conventional-commit form, which is acceptable here.

Full details: Linked Issues check

Explanation

Issue [#1310] requires returned 5xx responses to mark the worker server span as ERROR, set error.type to the status code, and avoid message text. It also requires returned 4xx responses to remain UNSET with test coverage. worker_otel.py adds post-response handling for status codes at or above 500. The reported tests verify 500 and 503 ERROR spans, 404 and 409 UNSET spans, status-based error.type, and no response-body text. Raised exceptions remain handled by the existing path.

Full details: Out of Scope Changes check

Explanation

The changed files are limited to the worker tracing implementation and its focused span test. The documentation update explains the changed middleware behavior. The test additions support issue [#1310]. No unrelated product behavior or unrelated files are identified.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 2 files.

Full details: Description check

Explanation

The description follows the repository template closely: it has a 'What and why' section that links issue #1310 and explains the problem and fix, and a 'How it was verified' section with a named test file, a fail-without-fix check, and local test, ruff, and shape-check results. The AI assistance section is filled in and names the tool. Most checklist items are ticked. The gaps are that CI is explicitly not green and the 'Tests added or updated' box is ticked, but the author states the test was run locally and CI status is unconfirmed. The description is substantive and specific, so the check passes.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

The API's export rule (_failed_type in core/observability/otel.py) keeps
an ERROR description only when it equals the span's error.type, and the
worker's own _failed sets the description to the error's type. "HTTP
500" would be dropped there; "500" is kept. Found in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Dave Arthur <davidarthur@hotmail.com>
@AutomatosAI
AutomatosAI merged commit 6146234 into main Nov 4, 2026
49 checks passed
@AutomatosAI
AutomatosAI deleted the fix/1310-worker-5xx-span-error branch November 4, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Worker tracing: a returned 5xx answer isn't marked as an error on its server span

2 participants