Skip to content

fix(tools): derive the tool-schema guard limits from the result ceiling - #234

Open
raghav-reglobe wants to merge 1 commit into
apache:masterfrom
raghav-reglobe:fix/schema-guard-follows-result-limits
Open

raghav-reglobe wants to merge 1 commit into
apache:masterfrom
raghav-reglobe:fix/schema-guard-follows-result-limits

Conversation

@raghav-reglobe

Copy link
Copy Markdown

Fixes #233.

What

Add SchemaLimits.for_result_bytes(), resolve a DorisToolsManager's limits from configured_result_limits() (with an explicit schema_limits override), build the dispatcher's guard from them, let create_doris_mcp_server follow the manager when no limits are passed, and put the validator's reason in the CHILD_RESULT_INVALID details.

Why

The runtime bounds rows by max_result_bytes, but the output guard applied its own defaults, so raising the ceiling silently did nothing past 1 MiB: results the runtime accepted came back as "did not match the declared schema", which sent people hunting through their SQL for a schema problem that was really a size cap. Two numbers for one intent, and the tighter one won without a word.

Behaviour

  • Default config: the guard admits the default 1 MiB ceiling plus the envelope (instance 2 MiB, nodes follow the bytes, one string up to the ceiling). Nothing shrinks below the previous defaults.
  • A larger configured ceiling scales the guard with it.
  • An explicit schema_limits on the manager or the server factory still wins.
  • details.reason distinguishes "exceeds output limits" from "does not match output schema".

Tests

test_schema_validation: the derivation, and a result inside the default ceiling that the default guard refuses and the derived guard admits (6,000 rows; a 300 KiB cell). test_tools_manager: resolution from config, the default, the explicit override. test_domain_dispatcher: the reason on both failure kinds. test_mcp_v2_protocol: the factory's resolution from the manager.

DomainDispatcher compiles every child's output schema with a bare
ToolSchemaGuard(), so the guard's instance limits stay at the library
defaults (1 MiB, 10,000 nodes, 256 KiB per string) whatever
PerformanceConfig.max_result_bytes says. A result the query runtime had
already bounded to a larger configured ceiling was then refused one step
later as CHILD_RESULT_INVALID, with a message that did not say why.

- SchemaLimits.for_result_bytes(max_result_bytes) derives limits from
  the ceiling: instance = ceiling + the base instance budget (the
  envelope around the rows), nodes = instance / 2 so the byte limit stays
  the binding one, one string may be as long as the result; nothing
  shrinks below the base.
- DorisToolsManager resolves its limits from configured_result_limits()
  and hands the dispatcher a guard built from them; an explicit
  schema_limits argument wins.
- create_doris_mcp_server follows the tools manager's limits when no
  schema_limits is passed (an explicit value still wins).
- The CHILD_RESULT_INVALID envelope carries the validator's reason in
  details.reason ("exceeds output limits" vs "does not match output
  schema").

Tests cover the derivation, the default-vs-derived guard on a result
inside the default ceiling, the manager and factory resolution, and the
reason on the error envelope.
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.

Output schema guard ignores the configured result ceiling and refuses results the query runtime already accepted

1 participant