{"record":{"id":"4adcf360f8115111","repo":"dbt-labs/dbt-core","slug":"expirationtime-does-not-conform-to-rfc-3339-thi","errorCode":null,"errorMessage":"'ExpirationTime' does not conform to RFC-3339. This is a driver bug.","messagePattern":"'ExpirationTime' does not conform to RFC-3339\\. This is a driver bug\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/relation/bigquery/config/components/refresh.rs","lineNumber":97,"sourceCode":"            .map(|s| {\n                parse_duration(s)\n                    .map(|v| v.as_secs() as f64 / 60.0)\n                    .unwrap_or(DEFAULT_INTERVAL_MIN)\n            })\n            .unwrap_or(DEFAULT_INTERVAL_MIN),\n        // NOTE: dbt set this to None, but the ADBC driver provides it under\n        // MaterializedView.MaxStaleness.\n        //\n        // This is a deviation from Core.\n        // https://github.com/dbt-labs/dbt-adapters/blob/2a94cc75dba1f98fa5caff1f396f5af7ee444598/dbt-bigquery/src/dbt/adapters/bigquery/relation_configs/_options.py#L142\n        max_staleness: schema\n            .metadata\n            .get(\"MaterializedView.MaxStaleness\")\n            .map(|s| s.to_owned())\n            .unwrap_or_else(|| \"\".to_owned()),\n        expiration: schema.metadata.get(\"ExpirationTime\").map(|s| {\n            DateTime::parse_from_rfc3339(s)\n                .expect(\"'ExpirationTime' does not conform to RFC-3339. This is a driver bug.\")\n                .to_utc()\n        }),\n    };\n\n    Ok(new_component(cfg))\n}\n\nfn from_local_config(relation_config: &dyn InternalDbtNodeAttributes) -> AdapterResult<Refresh> {\n    let cfg = match relation_config.as_any().downcast_ref::<DbtModel>() {\n        None => Config {\n            enable: DEFAULT_ENABLE,\n            interval_min: DEFAULT_INTERVAL_MIN,\n            ..Default::default()\n        },\n        Some(model) => {\n            let model_cfg = model\n                .__adapter_attr__\n                .bigquery_attr","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/relation/bigquery/config/components/refresh.rs#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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').","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."],"exampleFix":"// before\nDateTime::parse_from_rfc3339(s)\n    .expect(\"'ExpirationTime' does not conform to RFC-3339. This is a driver bug.\")\n// after\nDateTime::parse_from_rfc3339(s).map_err(|e| AdapterError::new(\n    AdapterErrorKind::Internal,\n    format!(\"invalid ExpirationTime '{s}': {e}\")))?.to_utc()","handlingStrategy":"validation","validationCode":"use chrono::DateTime;\nfn valid_expiration(meta: &HashMap<String, String>) -> bool {\n    meta.get(\"ExpirationTime\")\n        .map(|s| DateTime::parse_from_rfc3339(s).is_ok())\n        .unwrap_or(true)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["bigquery","datetime","rfc3339","metadata","panic"],"backgroundTag":"invalid-date-format","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}