infiniflow/ragflow · error · Error
Failed to create skill folder
Error message
Failed to create skill folder
What it means
Thrown in web/src/pages/skills/hooks.ts:818 when fileManagerService.createFolder for the skill's top-level folder returns a non-zero business code. The HTTP call resolved, but the backend refused to create the folder — most commonly because a folder with the same name already exists under the space folder (a race with the existence check), or the parent_id is invalid/expired.
Source
Thrown at web/src/pages/skills/hooks.ts:818
if (existingVersion) {
message.error(
t('skills.versionExists') || 'This version already exists',
);
return false;
}
}
skillFolderId = existingSkill.id;
} else {
// Create skill folder
const folderRes = await fileManagerService.createFolder({
name: skillNameNormalized,
type: 'folder',
parent_id: spaceFolderId,
});
if (folderRes.data.code !== 0) {
throw new Error('Failed to create skill folder');
}
skillFolderId = folderRes.data.data?.id;
}
} else {
throw new Error('Failed to list skills folder');
}
if (!skillFolderId) throw new Error('Failed to get skill folder ID');
// Create version folder
const versionRes = await fileManagerService.createFolder({
name: version,
type: 'folder',
parent_id: skillFolderId,
});
if (versionRes.data.code !== 0) {View on GitHub (pinned to 554fb1133a)
Solutions
- Treat 'already exists' code as success: re-list and reuse the existing folder id instead of throwing
- Handle the specific response message from createFolder in the error text
- Prevent duplicate submissions by disabling the upload button while a mutation is in flight
- Verify spaceFolderId is still valid (re-list) before creating
Example fix
// before
if (folderRes.data.code !== 0) {
throw new Error('Failed to create skill folder');
}
// after
if (folderRes.data.code !== 0) {
const { data: retryList } = await fileManagerService.listFile({
parent_id: spaceFolderId,
});
const existing = (retryList.data?.files || []).find(
(f: any) => f.name === skillNameNormalized && f.type === 'folder',
);
if (!existing) {
throw new Error(
folderRes.data.message || 'Failed to create skill folder',
);
}
skillFolderId = existing.id;
} Defensive patterns
Strategy: try-catch
Validate before calling
const folderNameFree = async (parentId: string, name: string) => {
const { data } = await fileManagerService.listFile({ parent_id: parentId });
return !(data.data?.files || []).some((f) => f.name === name && f.type === 'folder');
}; 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 and reuse */ }
else throw e;
} Prevention
- Disable the upload button while an upload is in flight to prevent duplicate creates
- Treat 'already exists' as reuse rather than failure
When it happens
Trigger: Two uploads of the same skill name in parallel: both pass the exists-check, the second create fails with 'already exists'; parent spaceFolderId deleted between steps; name rejected by backend sanitization; permission denied on the parent folder.
Common situations: Double-click on Upload. Uploading a skill that exists while the earlier listing was cached/stale. Space folder removed by another user mid-upload.
Related errors
- Failed to create directory: ${dirName}
- 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/06e2758198ccdd0d.
Report an issue: GitHub.