fix: async-task client crash, hidden-path resolution, and two unusable doc examples - #5706
Open
xianml wants to merge 4 commits into
Open
fix: async-task client crash, hidden-path resolution, and two unusable doc examples#5706xianml wants to merge 4 commits into
xianml wants to merge 4 commits into
Conversation
`SyncHTTPClient.<api>.submit()` raised `AttributeError: 'SyncHTTPClient' object has no attribute '_opened_files'` on every call: the `finally` block still cleaned up the pre-`ClientFileManager` attribute, so the request was sent and the task queued but the caller only ever saw the crash. `AsyncHTTPClient._submit` and `SyncHTTPClient._call` were already converted; this brings the last one over. The task endpoints had no test coverage anywhere in the suite, which is how this shipped. Adds a fixture with a trivial `@bentoml.task` service (no model, ~2.5 s for the file) covering submit/status/get/retry, submit with a file argument, and the async client. Two of the three fail before the fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`resolve_user_filepath` walked every part of the resolved absolute path, so a
hidden *ancestor* of the working directory made any relative reference illegal.
Serving a built bento whose `service.py` calls
`Image().requirements_file("requirements.txt")` therefore failed with
"Accessing hidden files is not allowed" whenever BENTOML_HOME was a dotted path:
BENTOML_HOME=~/.bentoml bentoml serve my_bento:latest
-> ValueError: .../.bentoml/bentos/my_bento/<ver>/src/requirements.txt
The path above cwd is not user input, and cwd containment is already enforced one
check earlier, so the hidden-file rule now applies to the relative part only.
Dotfiles inside the project, escaping cwd, absolute paths and /etc//proc stay
rejected — covered by the new tests, two of which fail before this change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`ResultStatus` is pending/in_progress/completed/failed/canceled, but the docs told readers to compare against 'success' and 'failure' — a branch that can never be taken — and the generated OpenAPI schema advertised the same wrong enum, so clients generated from the spec disagreed with the server. Verified against a running server: `GET /<api>/status` returns "completed". The two mutating routes were also swapped: retry is POST, cancel is PUT. Cancel is additionally unsupported by the local development server, which is now stated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s undefined Every snippet in "Custom service start command" passed `$PORT` (one also `$BENTOML_HOST`). `cmd` entries go through `expand_envs`, which substitutes from `os.environ` and raises on a missing key, and BentoML defines neither variable — so all four examples fail at startup with `KeyError: 'PORT'` (reproduced on 1.4.39). The port also has to match `http.proxy_port`, since that is where the proxy sends requests, and a custom-command Service defaults to `min(16, cpu/2)` workers of which only the first starts the process. Snippets now hard-code a port matching `proxy_port` and set `workers=1`, with a note covering both rules and what happens if `$VAR` is not in the environment. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jianshen92
approved these changes
Aug 26, 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.
What
Four correctness fixes, each found by exercising the SDK while writing an agent skill for authoring Bentos (#5705, which is now skill-only and does not depend on this PR). Two code fixes, each with a test that fails when the fix is reverted; two doc pages whose examples cannot work as written.
1.
SyncHTTPClient.<api>.submit()crashed on every callThe
finallyblock inSyncHTTPClient._submitstill cleaned up the pre-ClientFileManagerattribute._opened_filesmoved toClientFileManagerand is referenced nowhere else in the file, so everysubmit()raised — the request was sent and the task queued, but the caller only ever saw theAttributeError.AsyncHTTPClient._submitandSyncHTTPClient._callwere already converted; this brings the last one over.The async-task endpoints had no test coverage anywhere in the suite, which is how this shipped. Adds
tests/e2e/fixtures/tasks/(a trivial@bentoml.taskservice, no model) and three tests covering submit/status/get/retry, submit with a file argument, and the async client — ~2.6 s for the file. Two of the three fail before the fix.2. A hidden ancestor of the working directory made every relative path illegal
resolve_user_filepathwalked every part of the resolved absolute path, so any hidden directory above the working directory poisoned it. Serving a built bento whoseservice.pycallsImage().requirements_file("requirements.txt")therefore failed for any dottedBENTOML_HOME— and the loader swallows it as "not a valid bento tag", so the reported error is the unrelated module-import failure.The path above cwd is not user input, and cwd containment is already enforced one check earlier, so the hidden-file rule now applies to the relative part only. Dotfiles inside the project, escaping cwd, absolute paths and
/etc+/procall stay rejected — pinned by 7 new tests, two of which fail before the change.3. Task status values and the cancel/retry methods were wrong in the docs and in the OpenAPI schema
ResultStatusispending | in_progress | completed | failed | canceled, but the docs told readers to writeif status.value == 'success'/'failure'— branches that can never be taken — andTaskStatusResponseadvertised["in_progress", "success", "failure", "cancelled"], so a client generated from the spec disagrees with the server. Verified against a running server:GET /<api>/statusreturns"completed".The two mutating routes were also swapped in the docs: retry is POST, cancel is PUT. Cancel is additionally unsupported by the local development server (
"task cancellation is not supported in local development server"), which the page now says.4. Every "custom service start command" example fails at startup
cmdentries go throughexpand_envs, i.e.string.Template.substitute(os.environ), which raises on a missing key — and BentoML defines neitherPORTnorBENTOML_HOST. All four snippets on the page used them. Reproduced on 1.4.39, then verified that a hard-coded port matchinghttp.proxy_portproxies correctly (GET /→ 200 through the proxy).The snippets now hard-code a port matching
proxy_portand setworkers=1, with a note covering both rules — the command must listen onhttp.proxy_port, and a custom-command Service defaults tomin(16, cpu_count/2)workers of which only the first starts the process.Testing
tests/unit/_internal/utils/test_filesystem.py— 7 tests, 2 fail without fix 2.tests/e2e/bento_new_sdk/test_tasks.py— 3 tests, 2 fail without fix 1.tests/unitshows the same 23 pre-existing environment failures (missing protobuf/grpc extras locally) before and after these commits, with 9 added passes.🤖 Generated with Claude Code