dbt-labs/dbt-core · error
'primary_key' has a wrong type in StaticBaseRelationObject:
Error message
'primary_key' has a wrong type in StaticBaseRelationObject: '{primary_key}' What it means
`scd_args` accepts a `primary_key` that is either a list/iterable of columns or a single string. If the value is any other type (e.g. a dict, boolean, or number), the dispatcher raises this InvalidOperation error including the offending value's string form.
Source
Thrown at crates/dbt-adapter/src/relation/relation_object.rs:877
)
}
fn scd_args(&self, args: &[Value]) -> Result<Value, minijinja::Error> {
let iter = ArgsIter::new("Relation.scd_args", &[], args);
let primary_key = iter.next_kwarg::<Value>("primary_key")?;
let updated_at = iter.next_kwarg::<String>("updated_at")?;
iter.finish()?;
let mut scd_args = vec![];
match primary_key.kind() {
ValueKind::Seq => {
scd_args.extend(primary_key.try_iter()?.enumerate().map(|s| s.1.to_string()));
}
ValueKind::String => {
scd_args.push(primary_key.as_str().unwrap().to_string());
}
_ => {
return Err(minijinja::Error::new(
minijinja::ErrorKind::InvalidOperation,
format!(
"'primary_key' has a wrong type in StaticBaseRelationObject: '{primary_key}'"
),
));
}
}
scd_args.push(updated_at);
Ok(Value::from(scd_args))
}
}
#[cfg(test)]
mod tests {
use crate::relation::factory::create_static_relation;
use super::*;
use dbt_schemas::schemas::relations::DEFAULT_RESOLVED_QUOTING;View on GitHub (pinned to 0267ce9170)
Solutions
- Ensure `unique_key`/`primary_key` in the snapshot config is a string or a list of strings.
- Coerce the value before calling: wrap a single column as a one-element list or `| string`.
- Inspect the printed `{primary_key}` in the message to see the actual value and fix its source config.
Example fix
// before
{{ relation.scd_args(config.model.unique_key) }} // unique_key is a dict
// after
{% set pk = config.model.unique_key %}
{% if pk is not string and pk is not sequence %}
{% set pk = [pk | string] %}
{% endif %}
{{ relation.scd_args(pk) }} Defensive patterns
Strategy: validation
Validate before calling
{% set pk = config.get('unique_key') %}
{% if pk is string or pk is sequence and pk is not string %}
{{ relation.scd_args(pk) }}
{% else %}
{% do exceptions.raise_compiler_error('unique_key must be a string or list of strings') %}
{% endif %} Type guard
{% macro is_valid_pk(pk) %}
{{ return(pk is string or (pk is sequence and pk is not mapping and pk is not string)) }}
{% endmacro %} Prevention
- Keep `unique_key` configs as strings or lists of strings only.
- Coerce single non-string values with `| string` before calling scd_args.
- Add a schema check in CI for snapshot configs.
When it happens
Trigger: Calling `relation.scd_args(...)` (snapshot SCD argument building) where the `primary_key` argument resolves to a non-string, non-list Jinja value — e.g. a dict from `config.get('unique_key')` or a boolean.
Common situations: Snapshot configs where `unique_key` is a dict or None-derived value instead of a string or list of strings; macros passing `config.model.unique_key` through unmodified when it has an unexpected shape.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- role must be a string
- get_csv_data: argument must be an AgateTable
- remote_state must be Object
- Method '{method}' did not return a Table when called on a Ta
- Invalid arguments to doc macro
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/d98bf79edd235885.
Report an issue: GitHub.