Skip to content

fix(api): stop malformed time bounds reaching ClickHouse DateTime params - #627

Merged
Makisuo merged 1 commit into
mainfrom
worktree-fix-warehouse-datetime-params
Aug 25, 2026
Merged

fix(api): stop malformed time bounds reaching ClickHouse DateTime params#627
Makisuo merged 1 commit into
mainfrom
worktree-fix-warehouse-datetime-params

Conversation

@Makisuo

@Makisuo Makisuo commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Fixes five open error issues that turn out to be two instances of one shape: a time string that isn't a valid warehouse DateTime gets spliced into SQL and only fails at ClickHouse, as a 500 the caller can't act on.

1. MCP tools passed agent garbage straight through

normalizeTime returned unparseable input verbatim. An auto-investigation agent sent start_time="2026-08-47:53" to explore_attributes; that reached ClickHouse as toDateTime('2026-08-47:53') and surfaced as an unhandled McpQueryError + WarehouseMalformedQueryError.

  • normalizeTime now returns null when the input isn't a timestamp.
  • resolveTimeRange reports the bad bound in a new invalid array and substitutes the default window's bound for it, so st/et are always a well-formed warehouse DateTime — even for a caller that doesn't check the flag. Nothing malformed can reach the warehouse from this path any more.
  • The ten tools that already guard exceeded now also return timeRangeInvalidResult, which names the offending value and states the accepted formats, so the agent gets a retryable tool error instead of a parse failure.
  • invalid suppresses exceeded: a garbage bound collapses to the default window, whose width is under any cap, and reporting "range too large" there would send the agent chasing the wrong fix.

Issues: 55157217-4c27-488e-b944-136c5297c153, 125b5b63-652f-4ac2-be76-79a78d264770

2. v2ListMetrics sent fractional seconds to a plain DateTime column

parseWindow's precision option defaulted to "millisecond", but the metrics.list handler reads metric_catalog.Hour, which is a plain DateTime. Every call emitted toDateTime('2026-08-24 22:54:36.000') and failed with Cannot parse string … as DateTime, plus a matching TYPE_MISMATCH on the Hour <= … bound.

The hazard was already documented in the WindowPrecision doc comment — the default just made it opt-in. So:

  • The handler now asks for precision: "second".
  • precision is required. The eight raw-signal handlers (traces/logs/metrics on DateTime64 tables) state "millisecond" explicitly, which is exactly their current behaviour — no functional change there. The next rollup-backed handler can no longer inherit the unsafe default by omission.

Issues: 7010ecde-46f5-4835-8ddd-04c4122ae3f2, 2669196c-efe8-435c-a48c-1005696d6675, c66b38fd-3ab9-4cdb-95ad-418f86edd336

Testing

  • apps/api MCP suite: 364 passed
  • time.test.ts: 26 passed, including the real 2026-08-47:53 input, both-bounds-invalid, and the invalid-beats-exceeded precedence
  • telemetry.http.test.ts: 11 passed

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Two production error classes, one shape: a time string that isn't a valid
warehouse DateTime is spliced into SQL and only fails at ClickHouse.

MCP tools — normalizeTime returned unparseable input verbatim, so an
agent-supplied start_time of '2026-08-47:53' became
toDateTime('2026-08-47:53') and surfaced as an unhandled McpQueryError /
WarehouseMalformedQueryError. It now returns null; resolveTimeRange reports the
bad bound in `invalid` and substitutes the default window's bound, so st/et are
always well-formed even for a caller that doesn't check. The ten tools that
already guard `exceeded` now also return timeRangeInvalidResult, which names the
bad value and the accepted formats so the agent can retry.

v2 telemetry — parseWindow's `precision` defaulted to "millisecond", but
v2ListMetrics reads metric_catalog.Hour, a plain DateTime. Every call 500'd with
'Cannot parse string ...000 as DateTime' and a matching TYPE_MISMATCH. The
handler now asks for second precision, and `precision` is required so the next
rollup-backed handler can't inherit the unsafe default by omission.
@Makisuo
Makisuo merged commit e44b5ce into main Aug 25, 2026
28 checks passed
@Makisuo
Makisuo deleted the worktree-fix-warehouse-datetime-params branch August 25, 2026 12:48
@github-actions

Copy link
Copy Markdown

🍁 Maple PR preview

Warning

Preview cleanup could not be confirmed. The Alchemy teardown outcome was skipped.

Final commit 85ce564 · View workflow run

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.

1 participant