Fix empty search query validation

This commit is contained in:
adavyas 2026-03-28 20:10:47 -07:00
parent 131905d14a
commit db94ac050f
3 changed files with 40 additions and 9 deletions

View File

@ -552,11 +552,7 @@ class ConclusionBatchCreate(BaseModel):
class MessageSearchOptions(BaseModel):
query: Annotated[
str,
BeforeValidator(strip_nul_bytes),
Field(min_length=1, description="Search query"),
]
query: Annotated[str, Field(description="Search query")]
filters: dict[str, Any] | None = Field(
default=None, description="Filters to scope the search"
)
@ -567,15 +563,20 @@ class MessageSearchOptions(BaseModel):
description="Number of results to return",
)
@field_validator("query", mode="after")
@field_validator("query", mode="before")
@classmethod
def sanitize_query(cls, v: str) -> str:
if not v:
def sanitize_query(cls, v: Any) -> Any:
if not isinstance(v, str):
return v
sanitized = cast(str, strip_nul_bytes(v))
if v != "" and sanitized == "":
raise PydanticCustomError(
"string_too_short",
"String should have at least 1 character",
)
return v
return sanitized
# ---------------------------------------------------------------------------

View File

@ -689,6 +689,22 @@ def test_search_peer_empty_query(
assert isinstance(data, list)
def test_search_peer_nul_only_query_rejected(
client: TestClient, sample_data: tuple[Workspace, Peer]
):
"""Test peer search with a query that becomes empty after sanitization."""
test_workspace, test_peer = sample_data
response = client.post(
f"/v3/workspaces/{test_workspace.name}/peers/{test_peer.name}/search",
json={"query": "\x00", "limit": 10},
)
assert response.status_code == 422
error = response.json()["detail"][0]
assert error["loc"] == ["body", "query"]
assert error["type"] == "string_too_short"
def test_search_peer_nonexistent(
client: TestClient, sample_data: tuple[Workspace, Peer]
):

View File

@ -8,6 +8,7 @@ from src.schemas import (
DialecticOptions,
DocumentCreate,
DocumentMetadata,
MessageSearchOptions,
MessageCreate,
ObservationInput,
PeerCreate,
@ -217,6 +218,19 @@ class TestResolvedConfigurationMigration:
class TestSanitizedRequiredFields:
def test_message_search_query_allows_literal_empty_string(self):
search = MessageSearchOptions.model_validate({"query": ""})
assert search.query == ""
def test_message_search_query_rejects_nul_only_input(self):
with pytest.raises(ValidationError) as exc_info:
MessageSearchOptions.model_validate({"query": "\x00"})
error_dict = exc_info.value.errors()[0]
assert error_dict["loc"] == ("query",)
assert error_dict["type"] == "string_too_short"
def test_conclusion_content_rejects_nul_only_input(self):
with pytest.raises(ValidationError) as exc_info:
ConclusionCreate(