dbt-labs/dbt-core · error

remote_state must be Object

Error message

remote_state must be Object

What it means

After the None check, the BigQuery branch calls `as_object()` on remote_state_value and errors if it is not a minijinja object. The state must be an object that can be downcast to a RelationConfig; anything else (string, number, array, plain dict of the wrong shape) produces this InvalidArgument error.

Source

Thrown at crates/dbt-adapter/src/relation/relation_impl.rs:1284

                    RedshiftMaterializedViewConfigChangeset::new(remote_state, local_config);

                if changeset.has_changes() {
                    Ok(Value::from_object(changeset))
                } else {
                    Ok(Value::from(None::<()>))
                }
            }
            Bigquery => {
                if remote_state_value.is_none() {
                    return Err(minijinja::Error::new(
                        minijinja::ErrorKind::InvalidArgument,
                        "remote_state cannot be None",
                    ));
                }
                let current_state = remote_state_value
                    .as_object()
                    .ok_or_else(|| {
                        minijinja::Error::new(
                            minijinja::ErrorKind::InvalidArgument,
                            "remote_state must be Object",
                        )
                    })?
                    .downcast_ref::<RelationConfig>()
                    .ok_or_else(|| {
                        minijinja::Error::new(
                            minijinja::ErrorKind::InvalidArgument,
                            "remote_state must be RelationConfig",
                        )
                    })?;

                // TODO(serramatutu): minijinja_value_to_typed_struct does not work with
                // references, so we have to clone the value here...
                let local_config = minijinja_value_to_typed_struct::<InternalDbtNodeWrapper>(
                    local_config_value.clone(),
                )
                .map_err(|e| {

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Pass the RelationConfig object returned by the adapter's remote-state/describe API rather than a raw dict.
  2. If constructing state manually, build a RelationConfig via the adapter's relation helpers so downcast succeeds.
  3. Ensure you are not crossing adapter boundaries (BigQuery state must come from BigQuery describe results).

Example fix

// before
relation.changeset(remote_state={'columns': cols})
// after
relation.changeset(remote_state=remote_state)  # RelationConfig object from adapter
Defensive patterns

Strategy: type-guard

Validate before calling

{% if remote_state is not mapping %}
  {{ exceptions.raise_compiler_error('remote_state must be a RelationConfig object') }}
{% endif %}

Type guard

fn is_relation_config(v: &Value) -> bool {
    v.as_object()
        .and_then(|o| o.downcast_ref::<RelationConfig>())
        .is_some()
}

Try / catch

let cfg = remote_state_value.as_object()
    .and_then(|o| o.downcast_ref::<RelationConfig>())
    .ok_or_else(|| warn_and_refetch(relation))?;

Prevention

When it happens

Trigger: Passing a remote_state that is not a RelationConfig object — e.g. a primitive, list, or an unrelated object type — to the BigQuery changeset call.

Common situations: Hand-built remote state dicts in macros, passing the describe results object of a different adapter, or serialization round-trips that convert the RelationConfig into a plain value.

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


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/ec97085462622e41. Report an issue: GitHub.