dbt-labs/dbt-core · error
'ExpirationTime' does not conform to RFC-3339. This is a dri
Error message
'ExpirationTime' does not conform to RFC-3339. This is a driver bug.
What it means
While building the refresh/expiry component of a BigQuery materialized view config, the 'ExpirationTime' schema metadata is parsed with DateTime::parse_from_rfc3339 and .expect, so any timestamp not in strict RFC-3339 format panics. The message asserts the driver should always deliver an RFC-3339 ExpirationTime; malformed values indicate a driver bug rather than user error.
Source
Thrown at crates/dbt-adapter/src/relation/bigquery/config/components/refresh.rs:97
.map(|s| {
parse_duration(s)
.map(|v| v.as_secs() as f64 / 60.0)
.unwrap_or(DEFAULT_INTERVAL_MIN)
})
.unwrap_or(DEFAULT_INTERVAL_MIN),
// NOTE: dbt set this to None, but the ADBC driver provides it under
// MaterializedView.MaxStaleness.
//
// This is a deviation from Core.
// https://github.com/dbt-labs/dbt-adapters/blob/2a94cc75dba1f98fa5caff1f396f5af7ee444598/dbt-bigquery/src/dbt/adapters/bigquery/relation_configs/_options.py#L142
max_staleness: schema
.metadata
.get("MaterializedView.MaxStaleness")
.map(|s| s.to_owned())
.unwrap_or_else(|| "".to_owned()),
expiration: schema.metadata.get("ExpirationTime").map(|s| {
DateTime::parse_from_rfc3339(s)
.expect("'ExpirationTime' does not conform to RFC-3339. This is a driver bug.")
.to_utc()
}),
};
Ok(new_component(cfg))
}
fn from_local_config(relation_config: &dyn InternalDbtNodeAttributes) -> AdapterResult<Refresh> {
let cfg = match relation_config.as_any().downcast_ref::<DbtModel>() {
None => Config {
enable: DEFAULT_ENABLE,
interval_min: DEFAULT_INTERVAL_MIN,
..Default::default()
},
Some(model) => {
let model_cfg = model
.__adapter_attr__
.bigquery_attrView on GitHub (pinned to 0267ce9170)
Solutions
- Check the raw 'ExpirationTime' value and fix/upgrade the driver to emit RFC-3339 (e.g. '2026-01-01T00:00:00Z').
- Re-fetch metadata from the live BigQuery API to replace values written by older tooling.
- If epochs must be supported, branch on format: try parse_from_rfc3339 first, then fall back to numeric epoch via DateTime::from_timestamp.
- Replace .expect with a mapped AdapterError so malformed values fail gracefully with the offending value in the message.
Example fix
// before
DateTime::parse_from_rfc3339(s)
.expect("'ExpirationTime' does not conform to RFC-3339. This is a driver bug.")
// after
DateTime::parse_from_rfc3339(s).map_err(|e| AdapterError::new(
AdapterErrorKind::Internal,
format!("invalid ExpirationTime '{s}': {e}")))?.to_utc() Defensive patterns
Strategy: validation
Validate before calling
use chrono::DateTime;
fn valid_expiration(meta: &HashMap<String, String>) -> bool {
meta.get("ExpirationTime")
.map(|s| DateTime::parse_from_rfc3339(s).is_ok())
.unwrap_or(true)
} Prevention
- Ensure drivers emit ExpirationTime as RFC-3339 (e.g. 2026-01-01T00:00:00Z), never epoch numbers
- Pre-validate the timestamp format before relation reconciliation
- Support numeric-epoch fallback explicitly if mixed formats are unavoidable
- After driver upgrades, diff emitted metadata formats against the parser's expectations
When it happens
Trigger: from_remote_state (Config component) reads 'ExpirationTime' metadata containing a non-RFC-3339 timestamp — e.g. epoch millis ('1735689600'), epoch seconds as string, 'Z'-less datetimes without offset, or BigQuery's TIMESTAMP float-string form.
Common situations: Driver serializing the expiration as a numeric epoch instead of an ISO-8601 string; cached metadata written by an older adapter version; hand-built schemas in tests lacking proper formatting; timezone offset formats chrono's strict RFC-3339 parser rejects (e.g. '+00' instead of '+00:00').
Related errors
- No 'BIGQUERY:type' in field metadata. This is a driver bug.
- BigQuery returned invalid 'TimePartitioning.Field'. This is
- Could not parse 'RangePartitioning.Range.Start' as i64
- Could not parse 'RangePartitioning.Range.End' as i64
- Could not parse 'RangePartitioning.Range.Interval' as i64
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/4adcf360f8115111.
Report an issue: GitHub.