dbt-labs/dbt-core · error
name attribute must be a string
Error message
name attribute must be a string
What it means
Immediately after fetching the column `name` attribute, `reject_partition_field_column` asserts it is a string via `name.as_str().expect("name attribute must be a string")`. This panics when a column's `name` attribute exists but is a non-string Minijinja value (number, mapping, sequence). The comparison against the configured partition field requires a string.
Source
Thrown at crates/dbt-schemas/src/schemas/manifest/bigquery_partition.rs:189
}
pub fn reject_partition_field_column(
&self,
args: &[MinijinjaValue],
) -> Result<MinijinjaValue, MinijinjaError> {
let mut parser = ArgParser::new(args, None);
parser.check_num_args(current_function_name!(), 0, 1)?;
let columns = parser.get::<MinijinjaValue>("columns")?;
if let Ok(iter) = columns.try_iter() {
let columns = iter
.filter(|c| {
let name = c
.get_attr("name")
.expect("column must have a name attribute");
!name
.as_str()
.expect("name attribute must be a string")
.eq_ignore_ascii_case(self.field.as_str())
})
.collect::<Vec<_>>();
Ok(MinijinjaValue::from(columns))
} else {
Err(MinijinjaError::new(
MinijinjaErrorKind::InvalidArgument,
"columns must be a list of Column",
))
}
}
/// Return true if the data type should be truncated instead of cast to the data type
pub fn data_type_should_be_truncated(&self) -> bool {
!(self.data_type == "int64"
|| (self.data_type == "date"
&& match &self.__inner__ {
BigqueryPartitionConfigInner::Time(TimeConfig { granularity, .. }) => {View on GitHub (pinned to 0267ce9170)
Solutions
- Quote numeric or boolean column names in the model/schema YAML (`name: "123"`) so they deserialize as strings
- Validate at config-parse time that every column `name` is a string before rendering
- In custom adapters/templates, coerce the name with `.to_string()` instead of expecting `as_str()`
Example fix
// before
.as_str().expect("name attribute must be a string")
// after
match name.as_str() {
Some(s) => !s.eq_ignore_ascii_case(self.field.as_str()),
None => true,
} Defensive patterns
Strategy: type-guard
Validate before calling
// ensure every column name deserialized as a string
for col in &model.columns {
let name = col.get("name").expect("column missing name");
assert!(name.is_string(), "column name must be a string, got {:?}", name);
} Type guard
fn column_name_is_string(col: &MinijinjaValue) -> bool {
col.get_attr("name").map(|n| n.as_str().is_some()).unwrap_or(false)
} Try / catch
let ok = std::panic::catch_unwind(|| partition_cfg.render(alias));
if ok.is_err() { /* fall back to unfiltered columns */ } Prevention
- Always quote column names in YAML configs
- Coerce names to strings at config-parse time (name.to_string())
- Add a schema-level validation step for column name types
When it happens
Trigger: Rendering BigQuery partition SQL where a column entry's `name` resolves to a non-string value — e.g. YAML parsed `name: 2024` or `name: [a, b]` as a number/list, or a custom value object whose `name` attr is not stringifiable.
Common situations: Unquoted numeric column names in schema YAML (e.g. `name: 123`) that YAML deserializes as integers; generated configs injecting non-string names; adapter-specific column objects with structured name fields.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- remote_state must be Object
- column must have a name attribute
- {type(df)} is not a supported type for dbt Python materializ
- when data_type is date, inner must be a TimeConfig
- adapter.parse_partition_by failed on {raw_partition_by:?}: {
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/167fa25c039ea856.
Report an issue: GitHub.