diesel-rs/diesel · error

Can't get file name from path

Error message

Can't get file name from path `{path:?}`

What it means

This panic comes from diesel's `embed_migrations!` proc macro when building migration entries at compile time. `migration_literal_from_path` calls `Path::file_name()` on each entry in the migrations directory; `file_name()` returns None for paths ending in `..` or a filesystem root, so the macro panics instead of producing a migration name. It means the macro was given a path component from which no file/directory name can be extracted.

Solutions

  1. Pass a concrete, normalized migrations directory path to `embed_migrations!`, e.g. `embed_migrations!("migrations")`, not `.` or paths containing `..`.
  2. Verify at `CARGO_MANIFEST_DIR` level that the directory exists and its entries are real subdirectories (e.g. `migrations/2023-01-01-000000_create_users`).
  3. Run `diesel migration generate <name>` to create correctly shaped migration directories instead of hand-creating them.
  4. If the path is computed dynamically in a build script, canonicalize it (remove `.`/`..`) before embedding.

Example fix

// before
embed_migrations!("./migrations/..");
// after
embed_migrations!("migrations");
Defensive patterns

Strategy: validation

Validate before calling

let dir = std::path::Path::new("migrations");
assert!(dir.is_dir(), "migrations dir missing");
assert!(dir.file_name().is_some(), "path must end in a real directory name, not '.' or '..'");

Type guard

fn has_file_name(p: &std::path::Path) -> bool { p.file_name().is_some() }

Prevention

When it happens

Trigger: Calling `embed_migrations!` (or `embed_migrations!("path")`) with a path that resolves to `.`/`..` segments, a trailing path that reduces to a root, or a directory entry yielded by `read_dir` whose path has no final component.

Common situations: Pointing the macro at `"."` or `"migrations/.."`; build scripts or IDE-provided relative paths with `..` components; misconfigured MIGRATION_DIRECTORY env-style variables; moving the macros crate call so the implicit migrations path no longer exists as expected.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07). Data as JSON: /api/errors/a063824d3b414f28. Report an issue: GitHub.

Appendix: source

Thrown at diesel_migrations/migrations_macros/src/embed_migrations.rs:42

}

fn migration_literals_from_path(
    path: &Path,
) -> Result<Vec<proc_macro2::TokenStream>, Box<dyn Error>> {
    let mut migrations = migrations_directories(path)?.collect::<Result<Vec<_>, _>>()?;

    migrations.sort_by_key(DirEntry::path);

    Ok(migrations
        .into_iter()
        .map(|e| migration_literal_from_path(&e.path()))
        .collect())
}

fn migration_literal_from_path(path: &Path) -> proc_macro2::TokenStream {
    let name = path
        .file_name()
        .unwrap_or_else(|| panic!("Can't get file name from path `{path:?}`"))
        .to_string_lossy();
    if version_from_string(&name).is_none() {
        panic!(
            "Invalid migration directory: the directory's name should be \
             <timestamp>_<name_of_migration>, and it should contain \
             up.sql and optionally down.sql."
        );
    }
    let up_sql_path = path.join("up.sql");
    let up_sql_path = up_sql_path.to_str();
    let down_sql_path = path.join("down.sql");
    let metadata = TomlMetadata::read_from_file(&path.join("metadata.toml")).unwrap_or_default();
    let run_in_transaction = metadata.run_in_transaction;

    let down_sql = match down_sql_path.metadata() {
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => quote! { None },
        _ => {
            let down_sql_path = down_sql_path.to_str();

View on GitHub (pinned to 6fa6ed01b2)