You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AWS_ENDPOINT_URL_S3 silently overrides the explicit endpoint kwarg #753
When AWS_ENDPOINT_URL_S3 is set in the environment, S3Store(..., endpoint=...) ignores the kwarg and uses the env var. boto3 does the opposite: an explicit endpoint_url beats the env var. An explicitly passed argument losing to ambient environment is surprising, and there's no warning that it happened.
changed the title [-]AWS_ENDPOINT_URL_S3` silently overrides the explicit `endpoint` kwarg[/-][+]`AWS_ENDPOINT_URL_S3` silently overrides the explicit `endpoint` kwarg[/+]on Jul 20, 2026
In terms of obstore, explicit params always override environment variables IIRC. First we apply environment variables, then we apply explicit parameters, overriding if necessary.
The difference here is that upstream defines two different params. One that's s3-specific and one that's generic. Then it prefers the s3-specific endpoint.
Note store.config reports 'region-explicit' in all three rows while requests go to region-env — so the config getter actively misreports the live store, same as it does for the endpoint case here.
Different mechanism, though. This issue is a cross-key rule resolved at build time — Endpoint and S3Endpoint are distinct keys and build() does self.s3_endpoint.or(self.endpoint). The region case is a non-overwriting setter at set time:
so the explicit write is dropped where from_env() already set region. With AWS_DEFAULT_REGION that's the same config key losing to itself, which makes it a cleaner example of the complaint in this issue than the endpoint case.
Root cause for both: we call AmazonS3Builder::from_env() and then layer explicit config on top via with_config, assuming last-write-wins. Upstream breaks that assumption in exactly these two places.
The fixes don't overlap. Having obstore scan the env itself and merge into one config map (explicit wins) would fix default_region — only the explicit value would ever reach with_config, so or_else sees a fresh None. It would not fix the endpoint case: endpoint and endpoint_url_s3 would still both be present as distinct keys and build() would still prefer the S3-specific one. That one needs an explicit cross-key rule either way.
Worth noting the env-scan approach has its own blocker: AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN would land in self.config, which is a public getter and gets pickled. Today env credentials stay off that map, so it needs a field excluded from config/__getnewargs_ex__ rather than a straight merge.
(Unrelated to the precedence bug, #755 fixes two prefix-handling bugs in this area, including a panic reading .config on any store built with a client option.)
This doesn't feel entirely upstream. I think either obstore needs to override s3_endpoint as well (I don't see the difference from a consumer), or expose s3_endpoint so it can be overriden. From the consumer's perspective, explicit kwargs do not always override environment variables. And this makes it impossible to use obstore in environments that auto-inject AWS_ENDPOINT_URL_S3.
Activity
[-]AWS_ENDPOINT_URL_S3` silently overrides the explicit `endpoint` kwarg[/-][+]`AWS_ENDPOINT_URL_S3` silently overrides the explicit `endpoint` kwarg[/+]kylebarron commentedon Jul 21, 2026
Thanks for the issue.
In terms of obstore, explicit params always override environment variables IIRC. First we apply environment variables, then we apply explicit parameters, overriding if necessary.
The difference here is that upstream defines two different params. One that's s3-specific and one that's generic. Then it prefers the s3-specific endpoint.
So the fix to this would go upstream. Either by keeping them as only one parameter, or by making preference to the generic endpoint.
kylebarron commentedon Jul 21, 2026
Written by claude code; I haven't read through the below myself, but it may be helpful context for future me or future claude
Second instance of the same underlying problem, found while investigating this — worth fixing together, though the mechanisms differ.
Explicit
default_regionis silently dropped when eitherAWS_REGIONorAWS_DEFAULT_REGIONis set:Note
store.configreports'region-explicit'in all three rows while requests go toregion-env— so the config getter actively misreports the live store, same as it does for the endpoint case here.Different mechanism, though. This issue is a cross-key rule resolved at build time —
EndpointandS3Endpointare distinct keys andbuild()doesself.s3_endpoint.or(self.endpoint). The region case is a non-overwriting setter at set time:so the explicit write is dropped where
from_env()already setregion. WithAWS_DEFAULT_REGIONthat's the same config key losing to itself, which makes it a cleaner example of the complaint in this issue than the endpoint case.Root cause for both: we call
AmazonS3Builder::from_env()and then layer explicit config on top viawith_config, assuming last-write-wins. Upstream breaks that assumption in exactly these two places.The fixes don't overlap. Having obstore scan the env itself and merge into one config map (explicit wins) would fix
default_region— only the explicit value would ever reachwith_config, soor_elsesees a freshNone. It would not fix the endpoint case:endpointandendpoint_url_s3would still both be present as distinct keys andbuild()would still prefer the S3-specific one. That one needs an explicit cross-key rule either way.Worth noting the env-scan approach has its own blocker:
AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKENwould land inself.config, which is a public getter and gets pickled. Today env credentials stay off that map, so it needs a field excluded fromconfig/__getnewargs_ex__rather than a straight merge.(Unrelated to the precedence bug, #755 fixes two prefix-handling bugs in this area, including a panic reading
.configon any store built with a client option.)mscolnick commentedon Jul 21, 2026
This doesn't feel entirely upstream. I think either obstore needs to override
s3_endpointas well (I don't see the difference from a consumer), or exposes3_endpointso it can be overriden. From the consumer's perspective, explicit kwargs do not always override environment variables. And this makes it impossible to use obstore in environments that auto-injectAWS_ENDPOINT_URL_S3.kylebarron commentedon Jul 22, 2026
We can do that. In general I've tried to expose all parameters as-is from the underlying
object_store. We could add ans3_endpointparam to mirror https://docs.rs/object_store/0.14.1/object_store/aws/enum.AmazonS3ConfigKey.html#variant.S3Endpointmscolnick commentedon Jul 23, 2026
Adding an
s3_endpointwould be greatkylebarron commentedon Aug 5, 2026
Looking at upstream, you can already pass in
(Our local change would only be to update the type hint, so your editor knows it's a valid keyword parameter)
If we wanted to expand the allowed strings for that, we'd need to make an upstream change to add
s3_endpointorendpoint_s3or whatever on this line.