fix(cli): omit null/empty request fields so older instances accept them#2799
Merged
ZaynJarvis merged 1 commit intoJun 24, 2026
Merged
Conversation
The CLI unconditionally attaches optional fields to the find/search/add_resource
request bodies — `args` as an empty `{}` and `tags`/`context_type` as `null` —
even when the user never set them. OpenViking kernels use
`model_config = ConfigDict(extra="forbid")` on these routes, so any instance that
predates a field rejects the whole request with
`body.<field>: Extra inputs are not permitted`. This breaks whenever the CLI is
newer than the target instance (and, symmetrically, when a field is later
renamed/removed): e.g. `ov add-resource` fails on `body.args` against a pre-volcengine#2549
instance, and `ov find` fails on `body.tags` against a strict pre-volcengine#2706 instance.
- Add `compact_request_body()` and apply it in find/search/add_resource: drop
null-valued keys and an empty `args` object before sending. Scoped to these
read/create routes only, where a missing optional field and an explicit null
are equivalent — not applied globally, since null may mean "clear" on a future
update/PATCH route. This mirrors the existing `create_parent` backward-compat
convention.
- When a field is explicitly set but unsupported, translate the raw pydantic
`Extra inputs are not permitted` error into a version-mismatch hint and suggest
`ov health`, instead of surfacing the opaque API error.
Tests: unit tests for `compact_request_body` and `extra_forbidden_field`.
ZaynJarvis
approved these changes
Jun 24, 2026
ZaynJarvis
left a comment
Collaborator
There was a problem hiding this comment.
lgtm, fixes compatibility issue
9 tasks
t0saki
added a commit
that referenced
this pull request
Jun 25, 2026
…em (#2834) The Python SDK's find/search/add_resource unconditionally attach optional fields to their request bodies — `args` as an empty `{}` and `tags`/`score_threshold`/`filter`/`context_type`/`session_id` as `null` — even when the caller never set them. OpenViking kernels use `model_config = ConfigDict(extra="forbid")` on these routes, so any instance that predates a field rejects the whole request with `body.<field>: Extra inputs are not permitted`. This breaks the SDK (and every SDK consumer, e.g. vikingbot via `ov.AsyncHTTPClient`) against older instances: `add_resource` fails on `body.args` against a pre-#2549 instance, and `find` fails on `body.tags` against a strict pre-#2706 instance. This is the SDK-side counterpart of #2799, which fixed the same anti-pattern in the Rust CLI but left the Python SDK untouched. - Add `_compact_request_body()` and apply it in find/search/add_resource: drop null-valued keys and an empty `args` object before sending. Scoped to these read/create routes only, where a missing optional field and an explicit null are equivalent — not applied globally, since null may mean "clear" on a future update/PATCH route. Mirrors the CLI's `compact_request_body`. Tests: unit tests for `_compact_request_body` and for find/search/add_resource omitting unset optional fields while keeping explicitly-provided ones.
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.
Summary
The CLI unconditionally attaches optional fields to the
find/search/add_resourcerequest bodies —argsas an empty{}, andtags/context_typeasnull— even when the user never set them. Because OpenViking kernels declaremodel_config = ConfigDict(extra="forbid")on these routes, any instance that predates a given field rejects the entire request withbody.<field>: Extra inputs are not permitted. This patch stops sending those empty/null fields, and turns the raw rejection into an actionable hint when a field really is set but unsupported.Problem
The breakage is purely a field-set mismatch on
extra="forbid"routes: the set of fields the CLI sends must be a subset of the fields the target instance's model defines. It is not strictly "CLI newer than server" — it bites in both directions (newer CLI sending a not-yet-added field, or older CLI still sending a field the kernel later renamed/removed).Concrete cases observed against the Volcengine endpoint (same gateway, different instance versions selected by API key):
ov add-resource <url>against a pre-feat(resource): 支持飞书用户 token 导入 #2549 instance →body.args: Extra inputs are not permitted(kernel model has noargsfield; the route has beenextra="forbid"since fix(http): replace temp paths with upload ids #1012). The user never passed--args; the CLI sendsargs: {}regardless.ov find <query>against a strict pre-Set tags #2706 instance →body.tags: Extra inputs are not permitted(FindRequest becameextra="forbid"in feat(core): add actor peer filesystem view #2594 but thetagsfield only landed in Set tags #2706). The user never passed--tags; the CLI sendstags: nullregardless.Fix
compact_request_body()and apply it infind/search/add_resource: drop null-valued keys and an emptyargsobject right before sending. Scoped to these read/create routes only, where a missing optional field and an explicitnullare equivalent — deliberately not applied globally inpost, sincenullmay carry "clear this field" semantics on a future update/PATCH route. This generalizes the backward-compat convention already used forcreate_parent.Extra inputs are not permittedrejection (extra_forbidden_field) and render a version-mismatch hint instead of the opaque API error, plus anov healthaction to check the instance version.Verification
compact_request_body_drops_null_and_empty_args,compact_request_body_keeps_non_empty_args,extracts_extra_forbidden_field,ignores_non_extra_forbidden_errors— all pass.cargo test -p ov_cli --bins: all tests pass except one pre-existing failure (help_ui … missing clap command set-tags) that is unrelated to this change and reproduces onmainwith this patch stashed.ov findagainst an instance that previously failed withbody.tags: Extra inputs are not permitted.