dbt-labs/dbt-core · error
All snapshot macros should start with 'snapshot_'
Error message
All snapshot macros should start with 'snapshot_'
What it means
This is a Rust panic raised by `str::strip_prefix(...).expect(...)` while converting internal 'snapshot.*' macros back into snapshot .sql files during parse-time resolution of a package's snapshots. The parser assumes every macro whose uid starts with `snapshot.` also has a macro *name* starting with the `snapshot_` prefix, so the derived snapshot name (the macro name minus that prefix) can be used as the output filename `snapshots/<name>.sql`. If a snapshot macro's name lacks the prefix, the invariant is broken and the parser panics instead of silently producing a misnamed file.
Source
Thrown at crates/dbt-parser/src/resolve/resolve_snapshots.rs:140
stdfs::create_dir_all(&snapshots_dir)?;
}
// Save snapshots to the `snapshots` directory
let mut snapshot_files = Vec::new();
let mut sql_defined_snapshots = Vec::new();
// Map target path to original macro path for checksum recalculation
let mut snapshot_original_paths: HashMap<PathBuf, PathBuf> = HashMap::new();
let default_snapshots_path = vec![DBT_SNAPSHOTS_DIR_NAME.to_string()];
let mut synthetic_snapshot_macro_uids: HashSet<String> = HashSet::new();
for (macro_uid, macro_node) in macros {
if macro_node.package_name == package_name && macro_uid.starts_with("snapshot.") {
synthetic_snapshot_macro_uids.insert(macro_uid.clone());
// Write the macro call to the `snapshots` directory
let macro_call = format!("{{{{ {}() }}}}", macro_node.name);
let macro_name = macro_node.name.clone();
let snapshot_name = macro_name
.strip_prefix("snapshot_")
.expect("All snapshot macros should start with 'snapshot_'")
.to_string();
// Preserve file layout for proper fqn generation
let original_relative_path = strip_resource_paths_from_ref_path(
¯o_node.path,
package
.dbt_project
.snapshot_paths
.as_ref()
.unwrap_or(&default_snapshots_path),
);
let target_path = PathBuf::from(DBT_SNAPSHOTS_DIR_NAME)
.join(original_relative_path.with_file_name(format!("{snapshot_name}.sql")));
let snapshot_path = arg.io.out_dir.join(&target_path);
if let Some(parent) = snapshot_path.parent() {
stdfs::create_dir_all(parent)?;
}View on GitHub (pinned to 0267ce9170)
Solutions
- Rename the offending macro so its name starts with `snapshot_` (the snapshot file will then be emitted as `snapshots/<name-without-prefix>.sql`)
- Check for a stale `target/` directory and delete it so macros are re-parsed from source rather than from a stale manifest
- If the macro is not a real snapshot, move it out of the snapshot path/namespace so its uid no longer starts with `snapshot.`
- If this comes from a third-party package, report/patch the package or pin a version whose snapshot macros follow the `snapshot_` naming convention
Example fix
// before: macro name without required prefix
{% macro my_snapshot() %} ... {% endmacro %}
// after
{% macro snapshot_my_snapshot() %} ... {% endmacro %} Defensive patterns
Strategy: validation
Validate before calling
// before invoking the parser / in CI
for macro_node in snapshot_macros {
if macro_node.uid.starts_with("snapshot.") && !macro_node.name.starts_with("snapshot_") {
return Err(format!("snapshot macro '{}' must be named 'snapshot_*'", macro_node.name));
}
} Type guard
fn is_valid_snapshot_macro(name: &str) -> bool {
name.starts_with("snapshot_") && name.len() > "snapshot_".len()
} Prevention
- Always name snapshot macros with the `snapshot_` prefix; keep the prefix when renaming files or macros
- Never hand-edit `target/` artifacts; delete and regenerate instead
- Lint dbt packages in CI for macros whose uid starts with `snapshot.` but whose name lacks the prefix
- Keep third-party packages on versions that follow the standard snapshot macro naming convention
When it happens
Trigger: Running `dbt parse`/a build when a macro with uid starting `snapshot.` in the target package has a name that does not begin with `snapshot_` — e.g. a user-defined macro named like a snapshot (uid `snapshot.<pkg>.<name>` where name lacks the `snapshot_` prefix), a hand-edited or stale `target/` manifest, or an adapter/tool that synthesizes snapshot macros with an unexpected naming scheme.
Common situations: Users renaming a snapshot macro file or macro name without keeping the `snapshot_` prefix; packages written for other dbt tooling that name snapshot macros differently; generated/templated macros from scripts; upgrading a project that previously had a custom snapshot-naming convention into this parser.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Schema not found for canonical FQN: {}
- `EnterGuard` values dropped out of order. Guards returned by
- {e} {:?}
- {e}
- inconsistent park state; actual = {actual}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/1dbdaeff040238ac.
Report an issue: GitHub.