Spice v2.4.2 (Nov 9, 2026)
Spice v2.4.2 is now available! ๐ ๏ธ
Spice v2.4.2 is a patch release that continues security hardening and fixes Snowflake key-pair authentication. Security fixes limit the nesting depth, the expanded size, and the memory use of SQL queries, and HTTP datasets refuse redirects to other internal hosts. The release also fixes several SQL, Spice Cayenne, and runtime issues.
What's New in v2.4.2โ
SQL Query Limits Protect the Runtimeโ
Spice now limits the nesting depth, the expanded size, and the memory use of SQL queries. A query over a limit fails with HTTP 400 on /v1/sql, or with InvalidArgument on Flight SQL. The runtime continues to serve other queries. Before this release, any client that could send SQL could stop the runtime with one query. A deeply nested query overflowed the stack, and the process stopped with fatal runtime error: stack overflow, aborting. Other queries made one function or one plan allocate memory without a limit.
The checks apply to HTTP /v1/sql, /v1/nsql, Flight SQL statements and prepared statements, Flight SQL updates, and transactions. The checks cover these shapes:
- Long expressions. A chain of
+,||,AND, orORterms deeper than 512 levels fails. This includes a/v1/searchwherecondition. - Nested queries. Subqueries, or common table expressions (CTEs) that each read the CTE before them, fail past 64 levels.
- CTE expansion. A query fails when its CTE references expand to more than 4096 table references. The planner makes a copy of the plan of a CTE for each reference to it.
- Nested data types. A data type such as
ARRAY<ARRAY<โฆ>>fails past 32 levels. A type such asINT[][]โฆfails past 64 levels. - Arrow type strings. An Arrow type string, such as an
arrow_castargument or a column type that a dataset declares, fails past 64 levels. - Grouping sets. A
GROUP BYthat expands to more than 4096 grouping sets fails.CUBEof 13 expressions makes 8192 sets. 4096 is also the limit in PostgreSQL. - Search keywords. A
/v1/searchrequest with more than 512keywordsfails with HTTP 400.
These scalar functions now keep their output within runtime.query.memory_limit, or within a fixed cap:
lpadandrpadcharge the whole output buffer to the memory limit. This includes an empty fill string and negative lengths. A query that does not fit fails withResources exhausted.array_repeatandlist_repeatcharge the real size of a list, struct, binary, boolean, orNULLelement. Before this release, they charged 1 byte for each copy of such an element.flatten_json_properties,json_tree, andflatten_jsonstop at 32 รmax_bytesof output for one document.max_depthis limited to 128. A small JSON schema with repeatedallOfor$refentries no longer expands exponentially.truncatecuts text by characters, not bytes. Non-ASCII text made the query fail withQuery driver task ended unexpectedly.
Flight SQL metadata requests also have limits. GetSqlInfo info IDs and GetTables table types are limited to 1024 entries. GetTables and GetDbSchemas filter patterns are limited to 1024 bytes.
The limits are:
| Shape | Limit |
|---|---|
Expression depth, such as a chain of AND, OR, +, or || | 512 levels |
| Query nesting: subqueries, or CTEs that read each other | 64 levels |
| Table references after CTE expansion | 4096 |
SQL data type nesting with ARRAY, STRUCT, MAP, and similar keywords | 32 levels |
SQL data type nesting with [] | 64 levels |
| Arrow type string nesting | 64 levels |
GROUP BY grouping sets | 4096 (CUBE of up to 12 expressions) |
/v1/search keywords | 512 |
Flight SQL GetSqlInfo info IDs and GetTables table types | 1024 entries |
Flight SQL GetTables and GetDbSchemas filter patterns | 1024 bytes |
CTEs that do not read each other are not limited by depth. Table references outside of CTEs do not count toward the expansion limit.
Credentials Stay out of API Responses and Logsโ
GET /v1/datasets and GET /v1/catalogs no longer return credentials from the from value of a component. Before this release, any API key that could list components could read a password in a source URL, such as https://user:password@host/file.csv. This included a read-only key. The runtime now removes user:password@ from each URL. It replaces values of query keys such as password, secret, token, and sig with ***. With status=true, /v1/datasets also removes credentials from error_message. Sources with no credentials do not change.
The runtime also removes credentials from these errors and log lines:
- ADBC connection errors. Setup errors no longer contain
adbc_uri. The runtime replaces each configured secret in the driver message with***. Before this release, the full URI went to the warning log and to/v1/datasets?status=true. - MCP transport errors. The error no longer contains the URL of the MCP server. A URL can contain a credential.
.envfiles. The warning for a malformed line gives only the line number, not the line content.
HTTP Datasets Refuse Redirects to Other Internal Hostsโ
An http or https dataset in a file format, such as CSV or Parquet, no longer follows a redirect to an internal host. An internal host is a different host that is a loopback, private, or link-local address, or that resolves to one. The dataset fails with this error:
Refused to connect to <target>: the HTTPS data connector does not follow a redirect to a private, loopback, or link-local address
The host of the dataset itself is always allowed, also when it is internal. Redirects that stay on that host still work. SPICE_URL_TABLE_ALLOW_PRIVATE_HOSTS=true turns off the check.
Snowflake Key-Pair Authentication Fixโ
Snowflake datasets with key-pair authentication now load correctly. Before this release, such a dataset stopped at Initializing with this error:
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features.
Other Bug Fixesโ
IS [NOT] DISTINCT FROMwithANDorOR. These queries no longer return wrong boolean results or fail with an integer type error. For example,SELECT true IS DISTINCT FROM true OR truenow returnstrue, notfalse. The comparison now binds beforeANDorOR.COUNT(DISTINCT โฆ)on list or struct columns. A query with two or moreCOUNT(DISTINCT โฆ)aggregates no longer fails withResources exhaustedwhen one of them reads a list or struct column. Before this release, the query failed at about 50,000 rows and requested tens of GB. Each stored value held a reference to its whole input batch. This applied to federated and Cayenne queries, with or withoutGROUP BY.- Spice Cayenne file mode. At startup, a file-mode acceleration checks that the data files in its metastore exist and have the expected size. If they do not match, the acceleration reloads from the source or fails to load, and it does not serve incomplete data. Accelerations on S3 and in memory mode are not checked.
- Queries after a burst of stale cache hits. With
stale_while_revalidate_ttlset on the SQL results cache, new client queries no longer wait behind background revalidations. In a test, 600 stale hits made the next uncached query wait 321.8 seconds, and 6.3 seconds with this fix. At most one quarter of the query admission limit runs revalidations at the same time. A stale hit over that limit gets the cached result with no revalidation, andresults_cache_stale_swr_countcounts it. The runtime cancels a revalidation after 5 minutes and records the outcometimed_out. truncateon numbers.truncateno longer returns wrong values for integers and decimals near the limits of their type. For example,truncate(100, arrow_cast(50, 'Int8'))returned56, and the correct result is0. A result that does not fit its type is now an error.- SQL scalar functions with no arguments. A
from: sqlscalar function with no arguments no longer fails on every call. - Certificate errors in the CLI.
spiceHTTP commands, such asstatusandrefresh, report a TLS certificate failure as a TLS error. In v2.4.1, the release build reported it asThe Spice runtime is unavailable. - AWS session tokens. The runtime no longer sends an empty AWS session token together with static keys. A secret that is not set gives an empty token. This applies to S3, Delta Lake, and AWS SDK connectors.
Dependency Updatesโ
arrow-rs(Spice fork): 59.3.0 โ 59.3.2. This update fixes RUSTSEC-2026-0442 in run-end-encoded array validation, and it adds the 64-level limit for Arrow type strings.azure_security_keyvault_secrets: 0.10.0 โ 1.0.1. This update fixes RUSTSEC-2026-0438 in the Azure Key Vault secret store.azure_identityandazure_coremove to the 1.x line for that store.sqlparser: 0.62.0, vendored with the precedence fix from apache/datafusion-sqlparser-rs#2436.- DataFusion (Spice fork): the pin adds the fixes for
COUNT(DISTINCT โฆ)memory and for nested SQL data types.
Breaking Changesโ
Query limits. Queries and requests over the new limits fail with HTTP 400 or Flight InvalidArgument. Most of them stopped the runtime before this release, but some ran in v2.4.1. Examples are a GROUP BY CUBE of 13 expressions, a /v1/search request with more than 512 keywords, and a query whose CTEs expand to more than 4096 table references. For each limit, see SQL Query Limits Protect the Runtime.
HTTP dataset redirects. An http or https dataset in a file format fails when its server redirects to a different internal host. To allow it, set SPICE_URL_TABLE_ALLOW_PRIVATE_HOSTS=true.
JSON flattening. flatten_json, json_tree, and flatten_json_properties stop at 32 ร max_bytes of output for one document (256 MiB by default). They return the rows up to that point, with no error. The limit is on output, so a small document with long, deeply nested keys can reach it. To get all rows, increase max_bytes.
Upgradingโ
To upgrade to v2.4.2, use one of the following methods:
CLI:
spice upgrade
Homebrew:
brew upgrade spiceai/spiceai/spice
Docker:
Pull the spiceai/spiceai:2.4.2 image:
docker pull spiceai/spiceai:2.4.2
For available tags, see DockerHub.
Helm:
helm repo update
helm upgrade spiceai spiceai/spiceai --version 2.4.2
AWS Marketplace:
Spice is available in the AWS Marketplace.
Cookbook Updatesโ
No new cookbook recipes.
The Spice Cookbook provides recipes to help you get started with Spice.
Contributorsโ
What's Changedโ
Changelogโ
- [release/2.4] fix(sql): honour IS [NOT] DISTINCT FROM precedence before AND/OR (backport #15935) by @lukekim in #15936
- fix(snowflake): select the jsonwebtoken crypto provider at startup by @sgrebnov in #15988
- fix: reject over-deep SQL expressions and search keyword lists by @phillipleblanc in #15348
- Reject over-deep expressions before they overflow the query stack by @phillipleblanc in #15433
- Reject over-deep query nesting before planning by @phillipleblanc in #15722
- fix(sql): reject queries whose CTE references expand to too many table references by @phillipleblanc in #15766
- fix: bound nested SQL data types before parsing by @phillipleblanc in #15764
- fix(sql): limit the nesting depth of SQL data types by @phillipleblanc in #15705
- fix(query): reject GROUP BY that expands past 4096 grouping sets before planning by @phillipleblanc in #15843
- fix: limit Arrow type-string nesting depth on every parse path by @phillipleblanc in #15845
- fix(datafusion): charge lpad/rpad output buffers to the query memory limit by @phillipleblanc in #15846
- fix(runtime): reserve array_repeat output by element size by @phillipleblanc in #15885
- fix(udfs): bound JSON function expansion and output; fix truncate overflow and non-ASCII text by @phillipleblanc in #15912
- fix(flight): bound Flight SQL metadata request list and pattern sizes by @phillipleblanc in #15848
- fix(http): remove URL credentials from
fromin /v1/datasets and /v1/catalogs by @lukekim in #15834 - fix(adbc): keep the connection URI out of ADBC setup errors by @lukekim in #15835
- fix(http): refuse dataset redirects to other internal hosts by @phillipleblanc in #15877
- [2.4] fix(cayenne): don't serve a file-mode acceleration whose data files no longer match its metastore by @lukekim in #15943
- [release/2.4]fix(datafusion): charge each nested COUNT(DISTINCT) value for its own bytes (2.4) by @lukekim in #15986
- fix(cache): bound stale-while-revalidate background revalidations and give them a deadline by @phillipleblanc in #15820
- fix(cache): stop a timed-out stale-while-revalidate query that still waits for admission by @phillipleblanc in #15880
- fix(cli): use rustls for the HTTP client so certificate errors are recognized (2.4 backport of #15811) by @lukekim in #15984
- fix(deps): bump spiceai/arrow-rs to upstream 59.3.2 (2.4) by @lukekim in #16041
- fix(deps): bump azure_security_keyvault_secrets to 1.0.1 on release/2.4 (RUSTSEC-2026-0438) by @lukekim in #16043
- [release/2.4] fix(deps): replace temporary datafusion branch with spiceai-55-release-2.4 by @sgrebnov in #16046
- Update spicepod.schema.json by @github-actions in #15828
- ci: add rustfs-credentials action for GitHub OIDC credentials to RustFS by @phillipleblanc in #15976
- ci: move CI credentials to OIDC and environment secrets by @phillipleblanc in #16010
- ci: get RustFS credentials from the GitHub OIDC token by @phillipleblanc in #16005
- test: remove CI tests that need a live Dremio server by @phillipleblanc in #15973
- ci: authenticate BigQuery tests with workload identity federation by @sgrebnov in #16009
- ci: authenticate CI calls to Anthropic with workload identity federation by @lukekim in #15954
- ci: pin MongoDB 8.0 integration tests to 8.0.4 by @krinart in #15958
- ci: run the released-runtime spice chat E2E test against xAI by @Jeadie in #15974
- ci(cuda): least-privilege tokens and drop the MinIO copy by @sgrebnov in #16020
- ci: scope workflow jobs to GitHub environments by @Jeadie in #15966
- ci: pass secrets to run scripts through env, and use the read-write Postgres for load runs by @Jeadie in #15975
- [release/2.4] ci: move CI credentials to OIDC and environment secrets (backport) by @sgrebnov in #16035
- ci: fail a tag build when the tag does not match version.txt by @sgrebnov in #16021
- ci(docker): build release images on GitHub-hosted runners by @sgrebnov in #16022
- ci(release): cancel an older build of the same tag by @peasee in #16032
- [release/2.4] ci: hosted Docker release builds and release hardening by @sgrebnov in #16044
- ci: Use OIDC-based AWS roles for short-lived AWS credentials by @Jeadie in #16039
- [release/2.4] Revert workload identity for models and GitHub App keys in Key Vault/KMS by @Jeadie in #16052
- v2.4.2: remaining security backports, version bump to 2.4.2 by @sgrebnov in #16055
Full Changelog: https://github.com/spiceai/spiceai/compare/v2.4.1...v2.4.2

