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

adapter not found in context

Error message

adapter not found in context

What it means

Inside `submit_python_job`, the actual work is delegated to the `adapter` object looked up from the Jinja state. This `UndefinedError` is raised when no `adapter` is present in the current context, meaning the function was evaluated in a context where the adapter was never injected. The code comment notes this should only be reachable outside the run-node statement context, where the call would normally fail earlier as an unrecognized function.

Source

Thrown at crates/dbt-jinja-utils/src/phases/run/run_node_context.rs:819

            Error::new(
                ErrorKind::InvalidOperation,
                "compiled_code must be a string",
            )
        })?;

        // Note(Ani):
        // dbt-core validates:
        //   - macro_stack.depth == 2
        //   - call_stack[1] == "macro.dbt.statement"
        //   - "materialization" in call_stack[0]
        //
        // In fusion, we shouldn't need to do this because this funciton is only registered in the run node context
        // so if a user tries to use it outside of a statement.sql macro, in a materialization macro, it will fail earlier due to an unrecongized function call.

        // Get adapter from context and call submit_python_job
        let adapter = state
            .lookup("adapter", &[])
            .ok_or_else(|| Error::new(ErrorKind::UndefinedError, "adapter not found in context"))?;
        adapter.call_method(
            state,
            "submit_python_job",
            &[parsed_model.clone(), MinijinjaValue::from(compiled_code)],
            &[],
        )
    }
}

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Only call `submit_python_job` inside a run-node statement context (statement.sql for python models), not in materialization or other macros.
  2. Ensure the correct adapter is installed and selected so `adapter` is registered in the run node context.
  3. If hit in a custom macro, move the call into the model's compiled code/statement context instead.

Example fix

-- before (materialization macro)
{% do submit_python_job(model, code) %}
-- after (statement.sql context of a python model)
-- invoke via the standard python model execution path instead of calling it directly in a macro
Defensive patterns

Strategy: try-catch

Validate before calling

{# only call submit_python_job inside statement.sql / python model execution context #}
{% if 'adapter' not in context %}
  {{ exceptions.raise_compiler_error('submit_python_job requires the run node adapter context') }}
{% endif %}

Try / catch

match result {
    Err(e) if e.to_string().contains("adapter not found in context") => {
        // wrong phase/context: reroute the call into statement.sql execution
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling `submit_python_job` in a context built without the adapter binding — e.g. during parse phases, in a macro evaluated outside `statement.sql`, or in a context where `extend_base_context_stateful_fn`/`build_run_node_overlay` did not register `adapter`.

Common situations: Using `submit_python_job` in dbt_docs or analysis contexts; invoking it from a materialization macro rather than statement.sql; running with an adapter plugin missing so the adapter binding was never registered.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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