firecrawl/pdf-inspector · error · ModelStoreError::Io
could not allocate a unique model install file
Error message
could not allocate a unique model install file
What it means
create_temporary_file in src/vision/models.rs tries 16 times to create a unique '.{filename}.{pid}.{timestamp}.{seq}.part' file with create_new(true); if all 16 attempts collide with an existing file it returns ModelStoreError::Io with ErrorKind::AlreadyExists and message 'could not allocate a unique model install file'. This protects model installs: partial downloads are written to a .part file and atomically renamed, and this failure means the store could not reserve a scratch file.
Source
Thrown at src/vision/models.rs:570
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos();
let path = root.join(format!(
".{filename}.{}.{}.{}.part",
std::process::id(),
timestamp,
sequence
));
match OpenOptions::new().create_new(true).write(true).open(&path) {
Ok(file) => return Ok((path, file)),
Err(source) if source.kind() == io::ErrorKind::AlreadyExists => continue,
Err(source) => return Err(ModelStoreError::Io { path, source }),
}
}
let path = root.join(format!(".{filename}.part"));
Err(ModelStoreError::Io {
path,
source: io::Error::new(
io::ErrorKind::AlreadyExists,
"could not allocate a unique model install file",
),
})
}
#[cfg(not(windows))]
fn replace_file_atomic(source: &Path, target: &Path) -> io::Result<()> {
fs::rename(source, target)
}
#[cfg(windows)]
fn replace_file_atomic(source: &Path, target: &Path) -> io::Result<()> {
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::Storage::FileSystem::{
MoveFileExW, MOVEFILE_REPLACE_EXISTING, MOVEFILE_WRITE_THROUGH,
};
View on GitHub (pinned to 636ca1a58b)
Solutions
- Clear stale '.{filename}.*.part' files from the model root directory (the store's sweep_stale_install_files normally does this) and retry the install.
- Point the model store root at a local filesystem (not NFS/network mount) where O_EXCL create_new works reliably.
- Check filesystem permissions and free space on the model root; a persistent EACCES/ENOSPC surfaces as ModelStoreError::Io too.
- If it recurs, report it — 16 collisions of pid+nanotimestamp+counter indicates a platform filesystem bug.
Example fix
# before (model root on NFS) MODEL_STORE_ROOT=/mnt/nfs/models # after MODEL_STORE_ROOT=~/.cache/pdf-inspector/models
Defensive patterns
Strategy: retry
Validate before calling
// before model install: ensure root is a local, writable dir without stale part files
const fs = require('fs');
function prepareModelRoot(root) {
fs.mkdirSync(root, { recursive: true });
for (const f of fs.readdirSync(root)) {
if (f.startsWith('.') && f.endsWith('.part')) fs.rmSync(`${root}/${f}`, { force: true });
}
} Type guard
function isTempAllocFailure(e) {
return e instanceof Error && e.message.includes('could not allocate a unique model install file');
} Try / catch
try {
await store.ensureModel(name);
} catch (e) {
if (isTempAllocFailure(e)) {
cleanPartFiles(modelRoot);
await store.ensureModel(name); // one retry after cleanup
} else throw e;
} Prevention
- Keep the model store root on a local filesystem, not NFS/SMB, so create_new (O_EXCL) semantics work.
- Periodically clean leftover .part files from crashed installs.
- Ensure the process has write permission and free space in the model root.
- Avoid running many install processes simultaneously against the same root.
When it happens
Trigger: Downloading/installing a vision model into the model store when 16 consecutive create_new attempts all hit AlreadyExists — i.e. extreme filename collisions in the model root directory.
Common situations: A directory whose clock/timestamp resolution produces identical names (rare); a filesystem with broken create_new semantics (some network mounts, old NFS); leftover .part debris plus a frozen or wrapped counter; running many processes in lockstep on the same model root.
AI-assisted analysis of firecrawl/pdf-inspector@636ca1a58b (2026-09-05).
Data as JSON: /api/errors/caffdbfb8e488a2a.
Report an issue: GitHub.