databendlabs/databend · error · InvalidInput
s3.session-token requires s3.access-key-id and…
Error message
s3.session-token requires s3.access-key-id and s3.secret-access-key
What it means
The same validator rejects an S3 session token supplied without the key pair it belongs to. s3.session-token is a temporary credential that is only meaningful together with s3.access-key-id and s3.secret-access-key, so having the token alone is treated as InvalidInput.
Solutions
- Add both s3.access-key-id and s3.secret-access-key alongside s3.session-token; a session token is only valid with its key pair.
- If you do not need static temporary credentials, remove s3.session-token and rely on the ambient credential chain (IAM role).
- Double-check key spelling/whitespace in the properties map so the access/secret keys are actually recognized.
Example fix
// before
props.insert("s3.session-token".into(), "tok...".into());
// after
props.insert("s3.access-key-id".into(), "AKIA...".into());
props.insert("s3.secret-access-key".into(), "secret...".into());
props.insert("s3.session-token".into(), "tok...".into()); Defensive patterns
Strategy: validation
Validate before calling
let has_token = props.contains_key("s3.session-token");
let has_pair = props.contains_key("s3.access-key-id") && props.contains_key("s3.secret-access-key");
if has_token && !has_pair {
return Err("s3.session-token requires s3.access-key-id and s3.secret-access-key".into());
} Try / catch
// catch and surface as a credentials-completeness problem
if let Err(e) = file_io.get_operator_path(location) {
if e.message().contains("session-token requires") {
return Err(ConfigError::SessionTokenWithoutKeys);
}
return Err(e);
} Prevention
- Inject all three temporary-credential fields (key id, secret, token) from the same secret store entry.
- Verify key names exactly match 's3.access-key-id' / 's3.secret-access-key' — typos silently drop them.
- Rotate temporary credentials as a complete set, never the token alone.
When it happens
Trigger: build_operator -> validate_s3_credentials where props contains s3.session-token but is missing s3.access-key-id or s3.secret-access-key (or both).
Common situations: Users configuring STS/temporary credentials who paste the session token but omit the associated access/secret keys; automation that injects only the session token from an assumed-role secret; typo'd key names for the access/secret pair so they are not recognized.
Related errors
- s3.access-key-id and s3.secret-access-key must be…
- missing bucket in URL
- S3 params must remain S3
- value for enable_virtual_host_style is invalid
- failed to refresh Iceberg table credentials
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/c5b57efd7f725283.
Report an issue: GitHub.
Appendix: source
Thrown at src/common/storage/src/operator.rs:754
pub fn new(file_io: iceberg::io::FileIO) -> Self {
let (scheme, props, _extensions) = file_io.into_builder().into_parts();
Self { scheme, props }
}
fn validate_s3_credentials(&self) -> Result<()> {
let has_access_key = self.props.contains_key("s3.access-key-id");
let has_secret_key = self.props.contains_key("s3.secret-access-key");
let has_session_token = self.props.contains_key("s3.session-token");
if has_access_key != has_secret_key {
return Err(Error::new(
ErrorKind::InvalidInput,
"s3.access-key-id and s3.secret-access-key must be configured together",
));
}
if has_session_token && !(has_access_key && has_secret_key) {
return Err(Error::new(
ErrorKind::InvalidInput,
"s3.session-token requires s3.access-key-id and s3.secret-access-key",
));
}
Ok(())
}
fn build_operator(&self, location: &str) -> Result<(Operator, usize)> {
let url = url::Url::parse(location)
.map_err(|e| Error::new(ErrorKind::InvalidInput, e.to_string()))?;
let scheme = url.scheme();
// Handle file:// and memory:// URIs which don't have a host/bucket
let is_local_scheme = matches!(scheme, "file" | "memory" | "");
let (bucket, relative_path_pos) = if is_local_scheme {
// For file:// URIs, the path starts after "file://"View on GitHub (pinned to 288d84d76e)