infiniflow/ragflow · error · Error
Failed to create directory: ${dirName}
Error message
Failed to create directory: ${dirName} What it means
Thrown in web/src/pages/skills/hooks.ts:891 when creating a subdirectory of the uploaded skill's directory tree fails (createFolder code !== 0). The recursive walker creates missing intermediate folders (like src/utils) before uploading the file into the deepest one. Most common cause is a name collision — the folder was created between the list-check and the create — or an invalid parent after a concurrent modification.
Source
Thrown at web/src/pages/skills/hooks.ts:891
throw new Error(`Failed to list directory: ${dirName}`);
}
const existingDir = listData.data?.files?.find(
(f: any) => f.name === dirName && f.type === 'folder',
);
if (existingDir) {
currentParentId = existingDir.id;
} else {
// Create subdirectory
const createRes = await fileManagerService.createFolder({
name: dirName,
type: 'folder',
parent_id: currentParentId,
});
if (createRes.data.code !== 0) {
throw new Error(`Failed to create directory: ${dirName}`);
}
currentParentId = createRes.data.data?.id;
}
}
// Upload file to the final directory
const formData = new FormData();
formData.append('parent_id', currentParentId);
formData.append('file', file);
await fileManagerService.uploadFile(formData);
};
// Upload all files sequentially to avoid race conditions
for (const file of filteredFiles) {
await uploadFileWithStructure(file, versionFolderId);
}
View on GitHub (pinned to 554fb1133a)
Solutions
- Serialize folder creation per directory chain (or create all folders up-front) to eliminate the race
- On failure, re-list and reuse the folder if it now exists (someone else created it)
- Sanitize dirName (strip dots/slashes) before calling createFolder
- Surface createRes.data.message in the thrown error
Example fix
// before
const createRes = await fileManagerService.createFolder({
name: dirName,
type: 'folder',
parent_id: currentParentId,
});
if (createRes.data.code !== 0) {
throw new Error(`Failed to create directory: ${dirName}`);
}
currentParentId = createRes.data.data?.id;
// after
const createRes = await fileManagerService.createFolder({
name: dirName,
type: 'folder',
parent_id: currentParentId,
});
if (createRes.data.code !== 0) {
const { data: recheck } = await fileManagerService.listFile({
parent_id: currentParentId,
});
const nowExists = (recheck.data?.files || []).find(
(f: any) => f.type === 'folder' && f.name === dirName,
);
if (!nowExists) {
throw new Error(
`Failed to create directory: ${dirName} (${createRes.data.message})`,
);
}
currentParentId = nowExists.id;
} else {
currentParentId = createRes.data.data?.id;
} Defensive patterns
Strategy: fallback
Validate before calling
const sanitizedDirName = (name: string) => name.replace(/[/\\]/g, '').replace(/^\.+/, '').trim();
Try / catch
try {
const res = await fileManagerService.createFolder({...});
if (res.data.code !== 0) throw new Error(res.data.message);
} catch (e) {
if (/exists/i.test(e.message)) { /* re-list, reuse id */ } else throw e;
} Prevention
- Create the directory chain once (serialized) before uploading files into it, removing the race
- Sanitize directory names derived from webkitRelativePath
When it happens
Trigger: Parallel uploads of two files sharing a subdirectory: both see it missing, the second create loses the race; parent folder deleted mid-walk; dirName contains characters rejected by the backend (leading dot, slash); permission loss on the parent.
Common situations: Multi-file upload where Promise.all runs uploadFileWithStructure concurrently for files in the same new subfolder. Uploading OS junk paths (.DS_Store handled elsewhere, but similar hidden dirs). Space shared with another editor.
Related errors
- Failed to create skill folder
- Skills space not found
- Failed to list skills folder
- Failed to get skill folder ID
- Failed to create version folder
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/106f2c687486a35b.
Report an issue: GitHub.