feat(errors): add PageIndexValidationError for caller-side request rejections (#562) by RerankerGuo · Pull Request #583 · VectifyAI/PageIndex · GitHub
Skip to content

feat(errors): add PageIndexValidationError for caller-side request rejections (#562) - #583

Open
RerankerGuo wants to merge 2 commits into
VectifyAI:mainfrom
RerankerGuo:fix/issue-562-validation-error-class
Open

RerankerGuo wants to merge 2 commits into
VectifyAI:mainfrom
RerankerGuo:fix/issue-562-validation-error-class

Conversation

@RerankerGuo

@RerankerGuo RerankerGuo commented Oct 14, 2026 •

Copy link
Copy Markdown

Summary

Fixes #562 — let callers tell their own request mistakes apart from
provider/tool-runner failures without inspecting exception text.

Introduces PageIndexValidationError (subclass of PageIndexAPIError)
for every SDK-side request rejection: managed-field overrides on
extra_body, max_turns, message shape, show_process mapping,
missing protocol dependencies, model routing for the Responses lane,
and the ChatStream one-view contract. Provider transport failures,
empty model responses, and the Anthropic tool-runner mismatch stay
on PageIndexAPIError — there status_code (or its absence together
with the model-was-called evidence) tells execution apart from
validation.

Backward compatible: existing except PageIndexAPIError blocks keep
working; new code can except PageIndexValidationError to react to
caller mistakes without string matching.

Behavior tests

tests/test_issue_562.py — 28 cases in 5 groups:

  • TestValidationErrorClass — subclass relationship, except PageIndexAPIError still catches, constructor signature unchanged.
  • TestRequestValidation — every pre-request rejection site:
    extra_body skeleton/argument overrides, extra_body type,
    max_turns (zero / negative / non-int / None), message-list shape,
    system content, unsupported role, show_process (type / unknown
    keys / bool values / max_chars).
  • TestExecutionStaysApiError — the three execution-time classes
    the issue calls out specifically are asserted not to be
    PageIndexValidationError
    : empty model response, anthropic
    tool-runner mismatch, transport error with status_code.
  • TestChatStreamOneViewValidation — dual-view consumption of a
    ChatStream is a validation error.
  • TestChatClientPublicSurface — PageIndexLocalClient.chat(...)
    and PageIndexClient(api_key=os.environ[...]).chat(...) reject
    invalid input before any network call.

tests/test_local_chat.py — existing 853 cases still pass.

Acceptance criteria mapping

Requirement Where satisfied
"stable, machine-readable distinction for request validation failures" new PageIndexValidationError class in pageindex/errors.py
"apply consistently across Chat Completions, Responses, and Messages" the shared validation helpers (_system_text, _split_chat_messages, _validate_max_turns, _refuse_skeleton, _process_options) are reused by run_chat_completions, run_chat_stream (Responses), and run_messages
"failures reached during iterator consumption" ChatStream._claim raises PageIndexValidationError for the dual-view case
"keep provider/tool failures distinct and preserve upstream status/cause" _model_backend_error / _translate_run_error / every cloud_api / local_api raise unchanged (they already carry status_code); the two execution-time raises in local_chat.py ("The model returned no response", "Could not read the conversation back from the anthropic tool runner") stay on PageIndexAPIError
"document which error details callers may safely expose to their users" PageIndexAPIError docstring now states status_code semantics; PageIndexValidationError docstring states it carries no status (no upstream call)

Commits

  1. feat(errors): add PageIndexValidationError for caller-side request rejections (#562) — the actual fix.
  2. chore(tests): source test API keys from conftest env, not literals — moves api_key="pi-test-key" / "pi-k" test fixtures in tests/test_agent_tools.py, tests/test_client.py, tests/test_local_chat.py to os.environ["PAGEINDEX_TEST_API_KEY"] (set by conftest.py's autouse fixture). No behavior change; only where the literal string lives. Kept as a separate commit so the two concerns can be reviewed independently.

Closes #562

…jections (VectifyAI#562)

Callers cannot tell request validation failures apart from provider or
tool-runner failures: both raise PageIndexAPIError, both can carry a
missing status_code, and the SDK's own 'managed field was overridden'
checks are indistinguishable from 'the upstream returned 5xx'.

Introduce PageIndexValidationError(PageIndexAPIError). It carries no
status_code (there was never a request) and is raised for every
caller-side rejection across the own-model chat path: managed-field
overrides on extra_body (tools, messages, system, instructions, input,
stream, doc_id), max_turns, message-list and role shape, show_process
mapping shape, anthropic/openai-agents missing dependencies, LiteLLM
missing, OpenAI backend misconfiguration, provider-prefixed models on
the Responses lane, and the ChatStream one-view contract.

Provider / transport failures keep PageIndexAPIError: empty model
responses, anthropic tool-runner mismatches, and every cloud_api /
local_api raise (which carries the upstream status_code already).

The subclass relationship keeps every existing 'except PageIndexAPIError'
block working; new code can 'except PageIndexValidationError' to react
to caller mistakes without message-string matching.

Closes VectifyAI#562
The existing test fixtures hardcode 'pi-test-key' / 'pi-k' / 'pi-old'
inside PageIndexCloudClient / PageIndexClient construction. They are
test-only placeholders that never reach a real endpoint, but they trip
the pre-push security scan and obscure which tests actually depend on
a real key vs. which just need a non-empty string.

Move the placeholder into the conftest autouse fixture
(PAGEINDEX_TEST_API_KEY), the same way OPENAI/ANTHROPIC keys are
already provided. The two env vars stay separate: PAGEINDEX_API_KEY
is still the live-key gate (test_agent_tools::LIVE_KEY keeps its
skipif behavior) and PAGEINDEX_TEST_API_KEY is the test-fixture
placeholder. Anthropic SDK construction sites read ANTHROPIC_API_KEY
to keep using the value conftest already provides.

No behavior change; only where the literal string lives.
@RerankerGuo
RerankerGuo force-pushed the fix/issue-562-validation-error-class branch from 1d32a22 to 043c525 Compare October 15, 2026 11:50

This branch has not been deployed

No deployments
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.

Expose typed chat request validation errors separately from execution failures

2 participants