{"record":{"id":"8e86818a1959f930","repo":"diesel-rs/diesel","slug":"invalid-migration-directory-the-directory-s-name","errorCode":null,"errorMessage":"Invalid migration directory: the directory's name should be <timestamp>_<name_of_migration>, and it should contain up.sql and optionally down.sql.","messagePattern":"Invalid migration directory: the directory's name should be <timestamp>_<name_of_migration>, and it should contain up\\.sql and optionally down\\.sql\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"diesel_migrations/migrations_macros/src/embed_migrations.rs","lineNumber":45,"sourceCode":"    path: &Path,\n) -> Result<Vec<proc_macro2::TokenStream>, Box<dyn Error>> {\n    let mut migrations = migrations_directories(path)?.collect::<Result<Vec<_>, _>>()?;\n\n    migrations.sort_by_key(DirEntry::path);\n\n    Ok(migrations\n        .into_iter()\n        .map(|e| migration_literal_from_path(&e.path()))\n        .collect())\n}\n\nfn migration_literal_from_path(path: &Path) -> proc_macro2::TokenStream {\n    let name = path\n        .file_name()\n        .unwrap_or_else(|| panic!(\"Can't get file name from path `{path:?}`\"))\n        .to_string_lossy();\n    if version_from_string(&name).is_none() {\n        panic!(\n            \"Invalid migration directory: the directory's name should be \\\n             <timestamp>_<name_of_migration>, and it should contain \\\n             up.sql and optionally down.sql.\"\n        );\n    }\n    let up_sql_path = path.join(\"up.sql\");\n    let up_sql_path = up_sql_path.to_str();\n    let down_sql_path = path.join(\"down.sql\");\n    let metadata = TomlMetadata::read_from_file(&path.join(\"metadata.toml\")).unwrap_or_default();\n    let run_in_transaction = metadata.run_in_transaction;\n\n    let down_sql = match down_sql_path.metadata() {\n        Err(e) if e.kind() == std::io::ErrorKind::NotFound => quote! { None },\n        _ => {\n            let down_sql_path = down_sql_path.to_str();\n            quote! { Some(include_str!(#down_sql_path)) }\n        }\n    };","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/diesel-rs/diesel/blob/6fa6ed01b24b24248ab2a611698d0a7c6a2e9120/diesel_migrations/migrations_macros/src/embed_migrations.rs#L27-L63","documentation":"Raised by `migration_literal_from_path` when a directory inside the migrations folder does not have a name starting with a timestamp/version (`<timestamp>_<name>`). The `embed_migrations!` macro parses each child directory name with `version_from_string`; if no numeric version prefix is found it panics with this message at compile time.","triggerScenarios":"A subdirectory of the embedded migrations path whose name does not start with `<timestamp>_` (e.g. `fix_users`, `temp`, or a name where the part before `_` is not parseable as a version number).","commonSituations":"Hand-creating migration folders with casual names; renaming a migration and accidentally removing the timestamp prefix; checkout leaving stray directories (`.git`, `node_modules`, editor dirs) inside `migrations/`; non-diesel migration folders copied in.","solutions":["Rename the offending directory to `<timestamp>_<name>` (timestamp ascending, e.g. `20230901120000_fix_users`).","Remove stray non-migration directories/files from the migrations folder.","Use `diesel migration generate <name>` so naming is always valid.","Check `cargo tree`/diesel version: very old timestamps (e.g. date-based) vs numeric schemas can matter; align names with your diesel version's expected format."],"exampleFix":"// before\nmigrations/fix_users/up.sql\n// after\nmigrations/20230901120000_fix_users/up.sql","handlingStrategy":"validation","validationCode":"use std::fs;\nfor e in fs::read_dir(\"migrations\").unwrap() {\n    let name = e.unwrap().file_name().to_string_lossy().into_owned();\n    let Some((version, _)) = name.split_once('_') else {\n        panic!(\"bad migration dir: {name}\")\n    };\n    assert!(!version.is_empty() && version.chars().all(|c| c.is_ascii_digit()), \"bad version in {name}\");\n}","typeGuard":"fn valid_migration_name(name: &str) -> bool {\n    match name.split_once('_') {\n        Some((v, rest)) => !v.is_empty() && v.chars().all(|c| c.is_ascii_digit()) && !rest.is_empty(),\n        None => false,\n    }\n}","tryCatchPattern":null,"preventionTips":["Use `diesel migration generate <name>` for every migration.","Never rename away the `<timestamp>_` prefix.","Keep the migrations dir free of stray folders (CI check with the validator above)."],"tags":["compile-time","migrations","naming","proc-macro"],"backgroundTag":"invalid-identifier-format","analyzedSha":"6fa6ed01b24b24248ab2a611698d0a7c6a2e9120","analyzedAt":"2026-09-07T01:50:13.074Z","contentChangedAt":"2026-09-07T01:50:13.074Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}