{"record":{"id":"8e1848350c0e0c7d","repo":"dbt-labs/dbt-core","slug":"time-partitioning-field-must-be-a-string","errorCode":null,"errorMessage":"time_partitioning_field must be a string","messagePattern":"time_partitioning_field must be a string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-schemas/src/schemas/manifest/bigquery_partition.rs","lineNumber":240,"sourceCode":"            Self::PARTITION_TIME\n        };\n        Ok(MinijinjaValue::from(field))\n    }\n\n    /// Return the insertable time partitioning field name based on the data type.\n    /// Practically, only _PARTITIONTIME works so far.\n    pub fn insertable_time_partitioning_field(&self) -> Result<MinijinjaValue, MinijinjaError> {\n        Ok(MinijinjaValue::from(Self::PARTITION_TIME))\n    }\n\n    /// Render the partition expression\n    pub fn render(&self, alias: Option<String>) -> Result<MinijinjaValue, MinijinjaError> {\n        let column = if !self.time_ingestion_partitioning() {\n            self.field.to_owned()\n        } else {\n            self.time_partitioning_field()?\n                .as_str()\n                .expect(\"time_partitioning_field must be a string\")\n                .to_owned()\n        };\n\n        let column = if let Some(alias) = &alias {\n            format!(\"{alias}.{column}\")\n        } else {\n            column\n        };\n\n        let result = if self.data_type_should_be_truncated() {\n            format!(\n                \"{}_trunc({}, {})\",\n                self.data_type,\n                column,\n                self.granularity()?\n            )\n        } else {\n            column","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-schemas/src/schemas/manifest/bigquery_partition.rs#L222-L258","documentation":"`PartitionConfig::render` panics when time-ingestion partitioning is active and `time_partitioning_field()` returns a value that is not a string (`expect(\"time_partitioning_field must be a string\")`). The rendered column expression (`alias.field`) requires the time-partitioning field to be a plain string; anything else is treated as a corrupted partition config.","triggerScenarios":"Calling `render`/`render_`/`render_wrapped` on a `PartitionConfig` where `time_ingestion_partitioning()` is true but `time_partitioning_field` yields a non-string Minijinja value — e.g. `time_ingestion_partitioning` config set with a structured/None field value instead of a column name string.","commonSituations":"Model config like `time_ingestion_partitioning:` with a misconfigured or empty field; configs produced by another tool or older dbt version storing the field as a non-string; YAML that deserialized the field as a number or mapping.","solutions":["Set `time_ingestion_partitioning` (or `time_partitioning_field`) in the model config as a plain quoted string column name","Validate the partition config shape before rendering (field must be a string when time-ingestion partitioning is enabled)","If you construct `PartitionConfig` programmatically, coerce the field with `.to_string()` before calling `render`"],"exampleFix":"// before\nself.time_partitioning_field()?.as_str().expect(\"time_partitioning_field must be a string\").to_owned()\n// after\nmatch self.time_partitioning_field()?.as_str() {\n    Some(s) => s.to_owned(),\n    None => return Err(MinijinjaError::new(...)),\n}","handlingStrategy":"validation","validationCode":"// before rendering\nif cfg.time_ingestion_partitioning() {\n    let f = cfg.time_partitioning_field().ok_or(\"missing field\")?;\n    if f.as_str().is_none() {\n        return Err(\"time_partitioning_field must be a string\".into());\n    }\n}","typeGuard":"fn has_string_time_field(cfg: &PartitionConfig) -> bool {\n    !cfg.time_ingestion_partitioning()\n        || cfg.time_partitioning_field().and_then(|v| v.as_str()).is_some()\n}","tryCatchPattern":"match std::panic::catch_unwind(|| cfg.render(Some(alias))) {\n    Ok(v) => v,\n    Err(_) => MinijinjaValue::from(\"\"), // or propagate a proper error\n}","preventionTips":["Configure time_ingestion_partitioning with a plain quoted column-name string","Validate partition config shape in a pre-render config pass","When building PartitionConfig programmatically, store the field via to_string()"],"tags":["bigquery","partitioning","config","panic"],"backgroundTag":"type-mismatch","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"}