dbt-labs/dbt-core · error · minijinja::Error (UnknownMethod)

Unknown method on Exceptions

Error message

Unknown method on Exceptions: {method}

What it means

The `exceptions` Jinja object only exposes a fixed set of methods (raise_compiler_error, raise_fail_fast_error, contract-check helpers, etc.). Calling any other method name on `exceptions` reaches the catch-all arm of the dispatch and raises UnknownMethod, indicating the requested method does not exist in this implementation.

Solutions

  1. Check the method name spelling against the implemented exceptions methods in crates/dbt-jinja-utils/src/functions/base.rs.
  2. Replace unimplemented helpers with supported ones (e.g. `raise_compiler_error`).
  3. If the helper genuinely is missing, implement it in the `call_method` dispatch of the Exceptions function.
  4. Pin the vendored package to a version whose macros match the supported API.

Example fix

# before
{% do exceptions.raise_compilor_error('bad config') %}

# after
{% do exceptions.raise_compiler_error('bad config') %}
Defensive patterns

Strategy: type-guard

Validate before calling

{# Jinja-side guard before calling a method on exceptions #}
{% if exceptions.raise_compiler_error is defined %}
  {% do exceptions.raise_compiler_error(msg) %}
{% else %}
  {{ log('exceptions helper unavailable', info=True) }}
{% endif %}

Type guard

// Rust-side guard before dispatch
fn is_supported_exceptions_method(method: &str) -> bool {
    matches!(method,
        "raise_compiler_error" | "raise_fail_fast_error" | "warn" | "log"
    )
}

Prevention

When it happens

Trigger: Jinja code calls `exceptions.<method>(...)` with a method name not handled by the match in `call_method`, e.g. misspelled `raise_compilor_error`, or methods available in upstream dbt-core but not implemented in this Rust Jinja utils library.

Common situations: Typos in macro code; porting Python-dbt macros that use unimplemented exceptions helpers; package macros written against a newer/older dbt API surface.

Related errors


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

Appendix: source

Thrown at crates/dbt-jinja-utils/src/functions/base.rs:1328

                });

                let name_part = snapshot_name
                    .as_deref()
                    .map(|n| format!("snapshot '{n}'"))
                    .unwrap_or_else(|| "snapshot table".to_string());
                let location_hint = metadata
                    .map(|(_, path)| format!("\n  --> {}", path.display()))
                    .unwrap_or_default();

                let warning = format!(
                    "Data type of {name_part} hard-delete timestamps ({snapshot_time_data_type}) does not match its 'updated_at'-derived timestamp columns ({updated_at_data_type}). Values written when closing out deleted rows will be implicitly converted. Override the 'snapshot_get_time' macro in your project to emit a matching type.{location_hint}"
                );

                emit_warn_log_message(ErrorCode::SnapshotTimestampMismatch, warning);

                Ok(Value::UNDEFINED)
            }
            _ => Err(Error::new(
                ErrorKind::UnknownMethod,
                format!("Unknown method on Exceptions: {method}"),
            )),
        }
    }
}

/// Insert `defer_relation` into a serialized graph node's mapping. When
/// `defer_nodes` has a matching entry the value is the dbt-core-shaped
/// `DeferRelation` dict; otherwise it's null. The key is always present so
/// users can write `node.defer_relation is not none` without hitting an
/// "undefined value" error. (#1366)
///
/// `to_value` is a closure that builds a serializable `DeferRelation` from
/// the deferred node, allowing this helper to be reused across the three
/// deferrable resource types without making the helper itself generic.
fn inject_defer_relation<L>(
    map: &mut dbt_yaml::Mapping,

View on GitHub (pinned to 0267ce9170)