dbt-labs/dbt-core · error · minijinja::Error (InvalidOperation)
Environment variables (starting with {DBT_INTERNAL_ENV_VAR_P
Error message
Environment variables (starting with {DBT_INTERNAL_ENV_VAR_PREFIX}) cannot be accessed here What it means
Environment variables whose names start with `_DBT` are reserved for dbt's internal machinery and are blocked from Jinja `env_var` access. This prevents user code from reading or depending on internal state variables, whose names and semantics may change between dbt versions. The check runs unconditionally, before any environment lookup or default fallback.
Source
Thrown at crates/dbt-jinja-vars/src/env_var.rs:64
if let Some(value) = overrides_fn.and_then(|f| f(var)) {
return Ok(value);
}
let is_secret = var.starts_with(SECRET_ENV_VAR_PREFIX);
if is_secret && !placeholder_on_secret_access {
let err = Error::new(
ErrorKind::InvalidOperation,
format!(
"Secret environment variables (starting with {SECRET_ENV_VAR_PREFIX}) \
cannot be accessed here"
),
);
return Err(err);
}
let is_internal = var.starts_with(DBT_INTERNAL_ENV_VAR_PREFIX);
if is_internal {
let err = Error::new(
ErrorKind::InvalidOperation,
format!(
"Environment variables (starting with {DBT_INTERNAL_ENV_VAR_PREFIX}) \
cannot be accessed here"
),
);
return Err(err);
}
match (std::env::var(var), default) {
(Ok(value), _) => {
if is_secret {
debug_assert!(placeholder_on_secret_access);
let value = Value::from(SECRET_PLACEHOLDER.replace("{}", var));
Ok(value)
} else {
if let Some(tracker) = tracker {
tracker(var, &value);View on GitHub (pinned to 0267ce9170)
Solutions
- Rename the variable so it does not start with `_DBT` and access it under the new name.
- Stop depending on internal dbt variables; use documented public env vars or `flags`/`invocation_id` context members instead.
- Pass the needed value explicitly as a dbt var (`--vars`) or a non-reserved environment variable.
Example fix
// before (Jinja)
{{ env_var('_DBT_INVOCATION_TMP_DIR') }}
// after
{{ env_var('MY_TMP_DIR', default='/tmp') }} <!-- avoid the reserved _DBT prefix --> Defensive patterns
Strategy: validation
Validate before calling
// Reject reserved prefix before rendering
fn is_reserved(name: &str) -> bool { name.starts_with("_DBT") } Prevention
- Do not create or depend on environment variables starting with _DBT
- Use documented public context members (flags, invocation_id) instead of internal vars
- Audit exported env vars in CI for the reserved _DBT prefix
When it happens
Trigger: Calling `{{ env_var('_DBT_SOMETHING') }}` with any name matching the `_DBT` prefix from Jinja. Unlike the secret check, no flag disables this — even `placeholder_on_secret_access = true` still errors at env_var.rs:64.
Common situations: Curious users or copy-pasted code attempt to read internal dbt variables (e.g. `_DBT_INTERNAL_...`) discovered via `env | log` debugging; scripts that blanket-export many `_DBT_*` vars and expect them visible in models.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Secret environment variables (starting with {SECRET_ENV_VAR_
- 'env_var': environment variable '{var}' not found
- describe_dynamic_table is not supported by the {} adapter
- describe_interactive_table is not supported by the {} adapte
- The 'statement' result named '{name}' has already been loade
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/5295430efd9c0c0b.
Report an issue: GitHub.