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

  1. Treat 'already exists' code as success: re-list and reuse the existing folder id instead of throwing
  2. Handle the specific response message from createFolder in the error text
  3. Prevent duplicate submissions by disabling the upload button while a mutation is in flight
  4. 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

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


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/06e2758198ccdd0d. Report an issue: GitHub.