{"id":"92c1e49fb15e09db","repo":"actix/actix-web","slug":"provided-path-has-no-filename","errorCode":null,"errorMessage":"Provided path has no filename","messagePattern":"Provided path has no filename","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"actix-files/src/named.rs","lineNumber":100,"sourceCode":"    pub(crate) encoding: Option<ContentEncoding>,\n    pub(crate) read_mode_threshold: u64,\n}\n\n#[cfg(not(feature = \"experimental-io-uring\"))]\npub(crate) use std::fs::File;\n\n#[cfg(feature = \"experimental-io-uring\")]\npub(crate) use tokio_uring::fs::File;\n\nuse super::chunked;\n\npub(crate) fn get_content_type_and_disposition(\n    path: &Path,\n) -> Result<(mime::Mime, ContentDisposition), io::Error> {\n    let filename = match path.file_name() {\n        Some(name) => name.to_string_lossy(),\n        None => {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"Provided path has no filename\",\n            ));\n        }\n    };\n\n    let ct = mime_guess::from_path(path).first_or_octet_stream();\n\n    let disposition = match ct.type_() {\n        mime::IMAGE | mime::TEXT | mime::AUDIO | mime::VIDEO => DispositionType::Inline,\n        mime::APPLICATION => match ct.subtype() {\n            mime::JAVASCRIPT | mime::JSON => DispositionType::Inline,\n            name if name == \"wasm\" || name == \"xhtml\" => DispositionType::Inline,\n            _ => DispositionType::Attachment,\n        },\n        _ => DispositionType::Attachment,\n    };\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/actix/actix-web/blob/937960ca67f20e14ffe2a075bf6d4593502be12c/actix-files/src/named.rs#L82-L118","documentation":"io::Error with kind InvalidInput and message 'Provided path has no filename' (named.rs:99-104) is returned by get_content_type_and_disposition when Path::file_name() returns None — the path's final component is a root or '..'. It propagates out of NamedFile::from_file / open / open_async, which call this helper to derive Content-Type and Content-Disposition. This is a programmer error in the path argument, not a runtime/network condition.","triggerScenarios":"Calling NamedFile::open(\"/\"), NamedFile::open(\".\"), NamedFile::from_file(file, \"foo/..\"), or any path whose last segment normalises away. file_name() returns None for such paths, hitting the error arm.","commonSituations":"Building a NamedFile path dynamically from user input or joining that yields a trailing separator, or passing a directory path where a file path was expected.","solutions":["Ensure the path passed to NamedFile::open/open_async/from_file has a real filename as its final component.","Validate user-derived paths with Path::file_name() before constructing a NamedFile.","Use Files (directory serving) for directory paths instead of NamedFile."],"exampleFix":"// before: path normalises to no filename\nNamedFile::open_async(base_dir.join(user_input)).await  // user_input could be \"..\"\n\n// after: require a concrete filename\nlet name = path.file_name().ok_or_else(||\n    io::Error::new(io::ErrorKind::InvalidInput, \"path must name a file\"))?\nNamedFile::open_async(base_dir.join(name)).await","handlingStrategy":"validation","validationCode":"// Validate that the path ends in a real filename before opening.\nuse std::path::Path;\nfn ensure_has_filename(p: &Path) -> io::Result<()> {\n    if p.file_name().is_none() {\n        Err(io::Error::new(io::ErrorKind::InvalidInput, \"path has no filename\"))\n    } else { Ok(()) }\n}","typeGuard":null,"tryCatchPattern":"// Handle the io::Result from open_async.\nmatch NamedFile::open_async(path).await {\n    Ok(f) => Ok(f),\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput => {\n        // path had no filename; reject the request as 400\n        Err(actix_web::error::ErrorBadRequest(\"invalid file path\"))\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Never derive a NamedFile path directly from raw user input without validation.","Prefer Path::file_name() to extract just the final component when serving user-named files.","Use the Files service for directory serving rather than NamedFile on directory-like paths."],"tags":["actix-files","named-file","path-validation","programmer-error"],"analyzedSha":"937960ca67f20e14ffe2a075bf6d4593502be12c","analyzedAt":"2026-08-06T01:15:46.978Z","schemaVersion":2}