{"record":{"id":"323879a6e34551a0","repo":"ducaale/xh","slug":"could-not-create-file-after-unreasonable-number-of-attempts","errorCode":null,"errorMessage":"Could not create file after unreasonable number of attempts","messagePattern":"Could not create file after unreasonable number of attempts","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/download.rs","lineNumber":105,"sourceCode":"            Ok(file) => Ok(Some(file)),\n            Err(err) if err.kind() == ErrorKind::AlreadyExists => Ok(None),\n            Err(err) => Err(err),\n        }\n    }\n    if let Some(file) = try_open_new(&file_name)? {\n        return Ok((file_name, file));\n    }\n    for suffix in 1..u32::MAX {\n        let candidate = {\n            let mut candidate = file_name.clone().into_os_string();\n            candidate.push(format!(\"-{suffix}\"));\n            PathBuf::from(candidate)\n        };\n        if let Some(file) = try_open_new(&candidate)? {\n            return Ok((candidate, file));\n        }\n    }\n    panic!(\"Could not create file after unreasonable number of attempts\");\n}\n\n// https://github.com/httpie/httpie/blob/84c7327057/httpie/downloads.py#L44\n// https://tools.ietf.org/html/rfc7233#section-4.2\nfn total_for_content_range(header: &str, expected_start: u64) -> Result<u64> {\n    let re_range = Regex::new(concat!(\n        r\"^bytes (?P<first_byte_pos>\\d+)-(?P<last_byte_pos>\\d+)\",\n        r\"/(?:\\*|(?P<complete_length>\\d+))$\"\n    ))\n    .unwrap();\n    let caps = re_range\n        .captures(header)\n        // Could happen if header uses unit other than bytes\n        .ok_or_else(|| anyhow!(\"Can't parse Content-Range header, can't resume download\"))?;\n    let first_byte_pos: u64 = caps\n        .name(\"first_byte_pos\")\n        .unwrap()\n        .as_str()","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/ducaale/xh/blob/2404aceecc08b0b2d100fedc96f57745cd5904dc/src/download.rs#L87-L123","documentation":"download_file panics via panic! after the retry loop in open_new_file exhausts all candidate filename attempts (N, N-1, N-2, ...) without being able to create an unused file. It is a deliberate internal-invariant violation rather than a recoverable Result error, meaning the filesystem appears to reject every candidate name.","triggerScenarios":"Downloading to a directory where the base name and every enumerated fallback candidate cannot be opened new (try_open_new returns None for all iterations), e.g. an unwritable directory or extreme filesystem contention.","commonSituations":"Download directory lacks write permission; candidate names collide with files that can't be opened due to permissions; a pathological FS where open with O_CREAT|O_EXCL fails for all candidates.","solutions":["Check write permissions on the target download directory before running","Free disk space and verify the filesystem is not read-only","Catch the panic at the download_file boundary (catch_unwind) or refactor open_new_file to return a typed error","Choose a different, writable output directory explicitly"],"exampleFix":"// before\nlet (path, file) = download_file(...).unwrap(); // panics\n// after\nlet result = std::panic::catch_unwind(|| download_file(...));\nmatch result {\n    Ok(Ok((path, file))) => { /* download */ },\n    _ => eprintln!(\"could not create download file; check directory permissions\"),\n}","handlingStrategy":"try-catch","validationCode":"// before calling download_file\nlet dir = target_dir.as_path();\nif !dir.is_dir() { anyhow::bail!(\"not a directory: {}\", dir.display()); }\nlet probe = dir.join(\".write_probe\");\nstd::fs::File::create(&probe).and_then(|_| std::fs::remove_file(&probe))\n    .context(\"download directory is not writable\");","typeGuard":"fn is_writable_dir(p: &Path) -> bool {\n    p.is_dir() && std::fs::metadata(p).map(|m| !m.permissions().readonly()).unwrap_or(false)\n}","tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| download_file(&url, &out_dir)));\nmatch result {\n    Ok(Ok((path, file))) => { /* use file */ }\n    Ok(Err(e)) => eprintln!(\"download failed: {e}\"),\n    Err(_) => eprintln!(\"could not create file after unreasonable number of attempts\"),\n}","preventionTips":["Ensure the download directory exists and is writable before starting","Check disk space and read-only mount status","Prefer passing an explicit writable output path","Wrap risky downloads in catch_unwind or refactor to Result-based errors"],"tags":["filesystem","panic","download","io"],"backgroundTag":"internal-invariant-violation","analyzedSha":"2404aceecc08b0b2d100fedc96f57745cd5904dc","analyzedAt":"2026-09-13T19:13:33.814Z","contentChangedAt":"2026-09-13T19:13:33.814Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}