v5.5.2 - Large Aggregation Pipelines and with_session Scoping
Aggregation Pipeline Encoding and Parse.with_session Scoping Fixes
A focused fix release for aggregations. Large aggregation pipelines that exceeded the request URL limit were silently failing with "Invalid aggregate stage '0'", and aggregations run inside a Parse.with_session block were not being scoped to the ambient session. Both are corrected, and the aggregation scoping checks now mirror the auth precedence used everywhere else in the SDK.
Changes
Large aggregation pipelines no longer fail with "Invalid aggregate stage '0'"
- FIXED: An aggregation whose request URL exceeds ~2KB (for example a
group_by,group_by_date,distinct, or customaggregatepipeline with a large$in/$match) is rewritten from a GET to a POST carrying_method=GET, with the query moved into the request body. The pipeline was sent in the body as a URL-encoded string, but Parse Server's aggregate endpoint only JSON-decodes query-string params, not body params — so the pipeline arrived as a raw string and was rejected withInvalid aggregate stage '0', causing the aggregation to return an empty result. The long-URL override now sends a JSON body for the aggregate endpoint so the pipeline is delivered as a real array (boolean params such asrawValuesare preserved as booleans). The historical URL-encoded override is unchanged forfindand other endpoints, which Parse Server already decodes correctly.
Aggregations inside Parse.with_session blocks are now scoped
- FIXED:
group_by_date,group_by,distinct, andcount(aggregation branch) now detect the ambient session token set byParse.with_sessionand treat the query as scoped — consistent with howParse::Client#requestalready scopes REST find/get/count calls in the same block. Previously the scoping checks consulted only the query instance's ownsession_token=/scope_to_user/scope_to_roleand ignored the fiber-local ambient session, so an aggregation inside awith_sessionblock ran unscoped as the master key and returned all rows regardless of ACL. When scoped and mongo-direct is available the aggregation auto-promotes (ACL/CLP enforced); when scoped and mongo-direct is unavailable it fails closed withParse::Query::MongoDirectRequiredrather than silently leaking rows. - FIXED:
group_by_datenow also fails closed (Parse::Query::MongoDirectRequired) when the query is scoped but mongo-direct is unavailable — matching the existing behavior ofgroup_by,distinct, andcount. Previouslygroup_by_datesilently fell back to the REST/aggregateendpoint in that case. - FIXED: A regression introduced in 5.5.1 where
group_by_date,group_by, and pipeline-based aggregations called inside aParse.with_sessionblock returned empty results{}. The ambient session token was forwarded as an HTTP session-token header (suppressing the master key), causing Parse Server's REST/aggregateendpoint — which is master-key-only — to return a 401/403. The REST aggregate call sites now forceuse_master_key: trueso the ambient cannot suppress it, unless the caller explicitly setuse_master_key: false. - CHANGED: An explicit
use_master_key: trueon a query now takes precedence over the ambientParse.with_sessiontoken when deciding whether an aggregation is scoped, mirroringParse::Client#request. A deliberate admin aggregation executed inside awith_sessionblock is treated as a master-key call and is no longer forced onto mongo-direct. - FIXED:
GroupBy#rawroutes scoped queries (including those insideParse.with_session) through the same enforcement path as the other aggregation terminals and consistently returns an array of raw rows, instead of bypassing ACL/CLP enforcement on the master-key-only REST/aggregateendpoint.
Commit: e32211a
Author: Adrian Curtin
Date: June 11, 2026