Repository navigation
Let workers name the HTTP code their query fails with; BTE refuses Pathfinder as 501 (v2.2.0) - #200
Merged
Merged
Conversation
…thfinder as 501
A worker could only fail a query one way: handle_task_failure sent plain
"ERROR" to finish_query, /query answered 500, and an ARS child of a failed
ARA query landed as a clean D/200 with no results. So BTE refusing a
Pathfinder query read as a crash to every caller, and as success to the ARS.
Workers now raise shepherd_utils.query_errors.QueryError (UnsupportedQueryError
= 501) to say how the query ends, and that code and its client-safe
description travel the whole way out:
- run_task_lifecycle passes the exception to handle_task_failure, which
sends finish_query a coded status ("ERROR 501") plus the description.
A plain exception still sends "ERROR" (500) and no description.
- finish_query stores both (status, and the existing but unused
shepherd_brain.description column) and hands them to the ARS intake.
- /query and /arax/query answer with the worker's code and put its
description in the body; /asyncquery_status reports the description.
- ars_premerge errors a failed ARA query's child E/<code> (500 when no
code was named), as upstream records an ARA answering non-200.
The code rides in the stored status text, so there is no schema change,
and a bare "ERROR" still means 500 everywhere. Codes outside 400-599 are
ignored, so a worker can't make a failed query answer 2xx/3xx.
The BTE and bte.lookup workers now raise UnsupportedQueryError for
Pathfinder queries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2yuRAujys2XXK6YPjSay3
Codecov Report❌ Patch coverage is
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Workers can now name the HTTP code their query fails with (BTE answers a Pathfinder query 501), and the ARS records a failed ARA query as E/<code>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S2yuRAujys2XXK6YPjSay3
maximusunc
pushed a commit
that referenced
this pull request
Nov 1, 2026
Worker image versions on the monitor dashboard (SHEPHERD_VERSION build arg, kept alongside this branch's latest-trapi-1.6 tags) and workers naming the HTTP code and description their query fails with. The ARAX route keeps attaching the logs to the response, as 1.6 does, and passes the failure description through; the lost-response test drops its 2.0 Response check. Version stays 1.3.4 (untagged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TtsBikU9y9AFQ5uu9tcioz
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.
Why
Every worker failure looked the same from outside.
handle_task_failurealways sentstatus: "ERROR"tofinish_query, and/queryanswered that with a 500. So when BTE refused a Pathfinder query, callers saw a crash, even though BTE was declining a query it doesn't support. TRAPI's code for that is 501 Not Implemented.Through the ARS it was worse: a failed ARA query's child was recorded as a clean
D/200with 0 results, so the failure didn't show up at all.Found while load-testing the mixed ARA profile with HelmsDeep: BTE's Pathfinder refusals were counted as errors and failed every checkpoint.
What
Only the ARA's own worker knows whether it broke or just doesn't do this kind of query, so the worker now decides the status code. The server gets no ARA-specific logic.
shepherd_utils/query_errors.py(new):QueryError(description, status_code)andUnsupportedQueryError(501). The code is stored in the existing status text as"ERROR 501", so there is no schema change. A bare"ERROR"still means 500, so queries that fail the old way read exactly as before. Codes outside 400–599 are ignored, so a worker can't make a failed query answer 2xx/3xx.run_task_lifecyclepasses the exception tohandle_task_failure. For aQueryError, that sendsfinish_querythe coded status plus its description, which is shown to callers. Any other exception still sends"ERROR", and its text isn't forwarded because it may not be safe to show callers. AQueryErroris logged without a traceback, since it isn't a crash.finish_query: stores the description inshepherd_brain.description. That column already existed but nothing wrote to it. Both the status and the description are passed on to the ARS intake./queryand/arax/query: answer with the worker's code. The description becomes the response'sdescriptionunless the ARA already set one./asyncquery_status: shows the description (it already read that column).ars_premergeintake: a failed ARA query's child becomesE/<code>(orE/500when no code was named), which is how upstream records an ARA answering non-200.TIMEOUTqueries are unchanged and still deliver their partial results asD/200. I added this todocs/ARS_PARITY_REGISTER.md.workers/bteandworkers/bte_lookup: raiseUnsupportedQueryError("BTE does not support Pathfinder type queries."), with the same message as before.pyproject.tomlandshepherd_server/openapi-config.yaml, following the same two-file pattern as the 2.1.0 bump.devel(including Monitor: show image version per worker; exclude running tasks from backlog #199) is merged into this branch. Image tags andSHEPHERD_VERSIONcome from the release tag viarelease.yml, so nothing else needs bumping.Behavior changes to review
E/500instead ofD/200. One side effect: if a workflow fails partway through, whatever results it gathered before the failure are no longer merged.ERRORstatus. I updatedtest_finish_async_query_with_a_lost_responseto match.Releasing
After merging, publish a GitHub release tagged
v2.2.0.release.ymlbuilds and pushes the images from that.Not in this PR
If a client gives
/asyncqueryits own callback URL, the body we POST back still doesn't say the query failed. That was already true for every failure, not just this one. Fixing it means changing howfinish_querybuilds that body without decoding it, so it's left for a follow-up.Testing
tests/unit/test_query_errors.py: status encoding,handle_task_failurewith and without aQueryError, andrun_task_lifecyclepassing the exception through.test_query_status.py("ERROR 501"→ 501 with the worker's description on/queryand/asyncquery_status; invalid codes fall back to 500; an ARA's own description wins),test_finish_query.py(status and description reach Postgres and the ARS intake task), andars/test_ars_premerge.py(E/501,E/500,TIMEOUTstillD/200).test_bte.pyandtest_bte_lookup.pyassertUnsupportedQueryErrorwithstatus_code == 501.develand bumping the version: 2019 passed, 0 failed. 86 ARAX parity tests could not run because the reference data they need isn't available in this environment. They fail before reaching anything this PR touches.black --checkpasses on the whole tree.Generated by Claude Code