dbt-labs/dbt-core · error · InvalidOperation

Invalid arguments to doc macro

Error message

Invalid arguments to doc macro

What it means

In lenient (non-strict) mode, doc() still requires its first positional argument to be a string; if args.get::<String>("") fails, this InvalidOperation error replaces the low-level conversion error. It indicates the doc macro was called with no usable first argument.

Source

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

        // because model/source/column descriptions still render through it.
        if self.strict && (args.kwargs_len() != 0 || !(1..=2).contains(&args.positional_len())) {
            return Err(Error::new(
                ErrorKind::InvalidOperation,
                "doc() takes one or two positional string arguments",
            ));
        }
        let (arg1, arg2) = if self.strict {
            // Both args are annotated `str`, so no coercion either.
            let package_or_name = args.get::<Arc<str>>("")?.to_string();
            let name = if args.positional_len() == 0 {
                None
            } else {
                Some(args.get::<Arc<str>>("")?.to_string())
            };
            (package_or_name, name)
        } else {
            let arg1 = args.get::<String>("").map_err(|_| {
                Error::new(
                    ErrorKind::InvalidOperation,
                    "Invalid arguments to doc macro",
                )
            })?;
            (arg1, args.get_optional::<String>(""))
        };

        let (doc, target_package, doc_name) = match &arg2 {
            // Two arguments: explicit package and doc name
            Some(doc_name) => (
                self.lookup_doc(&arg1, doc_name),
                arg1.clone(),
                doc_name.clone(),
            ),
            // One argument: search the configured package precedence, then any package
            None => {
                let doc = self
                    .package_search_order

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Pass a string doc name as the first argument: {{ doc('my_doc') }}.
  2. Ensure any variable used as the doc name is defined and renders to a string.
  3. Coerce or default the variable: {{ doc(my_var | default('fallback_doc')) }}.
  4. Enable strict mode if you want the clearer argument-count diagnostics.

Example fix

// before
{{ doc() }}
// after
{{ doc('order_status') }}
Defensive patterns

Strategy: validation

Validate before calling

{% if doc_name is not string %}{% do exceptions.raise_compiler_error('doc name must be a string') %}{% endif %}

Try / catch

{% set doc_name_str = doc_name | default('') | string %}
{{ doc(doc_name_str) if doc_name_str else '' }}

Prevention

When it happens

Trigger: Calling {{ doc() }} with no arguments, or with a non-string first argument (e.g. a number, list, or None) while strict mode is disabled.

Common situations: Templated calls like {{ doc(my_var) }} where my_var is undefined or non-string; refactored macros that dropped the doc name argument.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


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