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

  1. Serialize folder creation per directory chain (or create all folders up-front) to eliminate the race
  2. On failure, re-list and reuse the folder if it now exists (someone else created it)
  3. Sanitize dirName (strip dots/slashes) before calling createFolder
  4. 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

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


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