[fix](lance) Pass namespace-vended storage options through to the BE - #66805
Draft
FANNG1 wants to merge 1 commit into
Draft
[fix](lance) Pass namespace-vended storage options through to the BE#66805FANNG1 wants to merge 1 commit into
FANNG1 wants to merge 1 commit into
Conversation
A Lance REST catalog discarded the storage options a namespace vended for a
table, so any scan that relied on credential vending failed with:
open Lance dataset failed: Failed to get AWS credentials:
CredentialsNotLoaded("no providers in chain provided credentials")
The options were re-encoded twice on the way to the BE, through a five-entry
S3-only table used in both directions:
namespace vends access_key_id
-> FE LanceStorageOptions.forBackend aws_access_key_id -> AWS_ACCESS_KEY
-> TFileScanRangeParams.properties
-> BE kStorageKeys AWS_ACCESS_KEY -> aws_access_key_id
-> lance-c
That table was written to emit one canonical spelling, which is right for the
outbound direction, but reading it backwards makes it a parser that only
accepts the spelling it happens to emit. Anything else was dropped: credentials
under any other accepted alias, and every non-S3 provider's keys, which left
the catalog unable to use credential vending outside S3 at all. The failure was
also split across the two halves - the FE passed the vended map to the Lance
Java SDK untouched and resolved schema fine, so only the scan failed.
The namespace specification describes storage_options as configuration "passed
directly to Lance", so the protocol defines no key vocabulary and a client
cannot assume one. Stop re-encoding them:
- Add TFileScanRangeParams.lance_storage_options, carrying the options in
Lance's own vocabulary. It is set at ScanNode level, like paimon_options, so
credentials are not serialized once per fragment split.
- The FE now builds a single option map for both readers, so the FE SDK and
lance-c can no longer disagree about how a dataset is reached.
- The BE hands that map to lance-c as it arrives.
Two details worth calling out:
Vended aliases are renamed to the spelling this class emits before merging.
object_store resolves an alias and its canonical name to one config key and
keeps only one of the two values, chosen by hash order, so letting both through
would leave the effective credentials and addressing style up to chance. Only
the aws_-prefixed aliases are renamed; bare names such as "token" mean
different things across providers.
Catalog options now use the unprefixed spelling. object_store accepts both, but
it is also the field name the OpenDAL backend uses, and that one performs no
alias normalization.
Note for a rolling upgrade: an FE upgraded ahead of the BEs no longer puts
vended credentials into TFileScanRangeParams.properties, so a REST catalog with
no static credentials cannot be scanned until the BEs are upgraded too.
Verified end to end against Apache Gravitino 1.3.0's lance-rest service, which
vends the unprefixed spelling, using a catalog with no s3.access_key or
s3.secret_key: full scan, predicate pushdown and IVF_FLAT vector search all
return correct results where the scan previously failed.
The docker stub only ever vended aws_-prefixed keys, so the alias path had no
coverage. It now serves a second table under the unprefixed spelling, and
LanceStorageOptionsTest covers the merge directly - LanceStorageOptions had no
test of its own before.
Claude-Session: https://claude.ai/code/session_01M3mYXBKShBonG6Lg3br4Ld
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
FANNG1
marked this pull request as draft
August 16, 2026 12:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Fixes #66772 (problem 1).
A Lance REST catalog discarded the
storage_optionsa namespace vended for a table, so any scan relying on credential vending failed:The options were re-encoded twice on the way to the BE, through one five-entry S3-only table used in both directions:
That table was written to emit one canonical spelling, which is correct outbound. Reading it backwards turns it into a parser that accepts only the spelling it happens to emit, so everything else was dropped — credentials under any other accepted alias, and every non-S3 provider's keys, which left the catalog unable to use credential vending outside S3 at all.
The failure was also split across the two halves, which made it hard to read: the FE passes the vended map to the Lance Java SDK untouched, so
SHOW TABLESandDESCsucceeded and only the scan failed.The Lance Namespace specification describes
storage_optionsas configuration "passed directly to Lance", so the protocol defines no key vocabulary of its own and a client cannot assume one.Release note
Fixed a Lance REST catalog failing to scan with
CredentialsNotLoadedwhen it relied on credentials vended by the namespace rather than statics3.access_key/s3.secret_key.What is changed and how it works?
Stop re-encoding server-supplied options.
TFileScanRangeParams.lance_storage_options(new, id 38) carries the options in Lance's own vocabulary. Set at ScanNode level — the same pattern aspaimon_options— so credentials are not serialized once per fragment split.propertiesis deliberately not reused: it is copied wholesale intoio::FileSystemPropertiesfor the shared filesystem layer.forBackendis deleted._storage_optionshands that map to lance-c as it arrives;kStorageKeysand theallow_http/use_path_stylederivations are gone.s3()TVF path populates the same field, including the schema-fetch RPC.Two details worth review attention:
Vended aliases are renamed before merging.
object_storeresolves an alias and its canonical name to the same config key and keeps only one of the two values, chosen by hash order:So a namespace vending
aws_endpointwhile the catalog contributesendpointwould not override it; both would survive and Lance would pick between them unpredictably. Only theaws_-prefixed aliases are renamed — bare names such astokenmean different things across providers (S3 session token vs. Azure bearer token) and this layer does not know the provider.Catalog options now use the unprefixed spelling.
object_storeaccepts both, but the unprefixed name is also the field name used by the OpenDAL backend, which performs no alias normalization at all.allow_httpis derived after merging, from whichever endpoint ends up in use, since a namespace can replace the catalog's endpoint or supply the only one there is.Options that would change which data is read (
bucketand its aliases,root) are dropped from the vended map, mirroring the keys Lance itself protects.Rolling upgrade
An FE upgraded ahead of the BEs no longer puts vended credentials into
TFileScanRangeParams.properties, and an older BE reads only that. A REST catalog with no static credentials therefore cannot be scanned until the BEs are upgraded too. The Lance catalog is not in a release yet, so this only affects development clusters.How was this patch tested?
Unit tests.
LanceStorageOptionsTestis new —LanceStorageOptionshad no test of its own, andforBackendhad zero call sites in any test, which is why this went unnoticed. It covers the emitted spelling, alias renaming,allow_httpderivation, protected keys, non-S3 options, and empty/absent input.LanceThriftContractTestgains round-trip coverage of the new field.Regression. The docker stub only ever vended
aws_-prefixed keys, so the alias path had no coverage anywhere. It now serves a second table,all_types_unprefixed, backed by the same dataset but vending the unprefixed spelling, andtest_lance_rest_catalogscans it with no static credentials configured.End to end, against Apache Gravitino 1.3.0's
lance-restservice, which vends the unprefixed spelling. Catalog with nos3.access_key/s3.secret_key:CREATE CATALOG lance_novend PROPERTIES ( "type" = "lance", "lance.catalog.type" = "rest", "lance.rest.uri" = "http://127.0.0.1:9101/lance", "lance.namespace.parent" = "lance_catalog" ); SELECT count(*), min(row_id), max(row_id), sum(row_id) FROM lance_novend.doris_probe.rest_probe; -- 1034 1 1034 535095against a 1034-row, 2-fragment dataset with an IVF_FLAT index. Predicate pushdown and vector search both return correct results on the same catalog, and a catalog with static credentials is unaffected. Before this change the same statement failed with
CredentialsNotLoaded.https://claude.ai/code/session_01M3mYXBKShBonG6Lg3br4Ld