OtterMind/Chat2DB · warning · IllegalArgumentException

File or directory already exists

Error message

File or directory already exists

What it means

Thrown by SqlDirectoryTreeStore.createChild() when the target file or directory already exists at the resolved path. After validating the parent and containment, the method checks Files.exists with NOFOLLOW_LINKS. If a file or directory with the same name already exists in the parent, creation is rejected to avoid overwriting.

Source

Thrown at chat2db-community-server/chat2db-community-jcef/src/main/java/ai/chat2db/community/jcef/handler/biz/SqlDirectoryTreeStore.java:128

        Path root = getRoot(rootToken);
        Path parent = resolveInRoot(root, parentRelativePath);
        if (!Files.isDirectory(parent, LinkOption.NOFOLLOW_LINKS)) {
            throw new IllegalArgumentException("Selected path is not a directory");
        }

        boolean directory = "directory".equals(type);
        boolean file = "file".equals(type);
        if (!directory && !file) {
            throw new IllegalArgumentException("Unsupported SQL directory child type");
        }

        String name = file ? normalizeFileName(rawName, "sql") : normalizeDirectoryName(rawName);
        Path target = parent.resolve(name).normalize();
        if (!target.startsWith(root)) {
            throw new IllegalArgumentException("Path is outside of the selected SQL directory");
        }
        if (Files.exists(target, LinkOption.NOFOLLOW_LINKS)) {
            throw new IllegalArgumentException("File or directory already exists");
        }

        if (directory) {
            Files.createDirectory(target);
        } else {
            Files.createFile(target);
        }

        Path realTarget = target.toRealPath(LinkOption.NOFOLLOW_LINKS);
        if (!realTarget.startsWith(root)) {
            throw new IllegalArgumentException("Path is outside of the selected SQL directory");
        }

        Map<String, Object> result = new HashMap<>();
        result.put("createdNode", toNode(rootToken, root, realTarget));
        result.put("children", listChildren(rootToken, parentRelativePath));
        return result;
    }

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Refresh the parent's children list before allowing the create action to show existing names
  2. On the frontend, check for name collisions against the current children before submitting
  3. Handle the error response by showing 'A file with this name already exists' and suggesting an alternative name

Example fix

// before: no duplicate check on frontend
function onCreate(name, type) {
  createChild(rootToken, parentPath, name, type);
}

// after: check existing children first
function onCreate(name, type) {
  const exists = children.some(c => c.name.toLowerCase() === name.toLowerCase());
  if (exists) {
    showError('A file or directory with this name already exists');
    return;
  }
  createChild(rootToken, parentPath, name, type);
}
Defensive patterns

Strategy: validation

Validate before calling

// Before calling createChild, check for existing names
Path target = parent.resolve(normalizedName);
if (Files.exists(target, LinkOption.NOFOLLOW_LINKS)) {
    throw new IllegalArgumentException("File or directory already exists: " + normalizedName);
}
SqlDirectoryTreeStore.createChild(rootToken, parentRelativePath, name, type);

Try / catch

try {
    Map<String, Object> result = SqlDirectoryTreeStore.createChild(rootToken, parentRelativePath, name, type);
    ResponseBuilder.buildSuccessJcef(Map.of("data", result), callback);
} catch (IllegalArgumentException e) {
    callback.failure(409, e.getMessage()); // 409 Conflict is semantically correct
}

Prevention

When it happens

Trigger: Invoked via create-sql-directory-child when a file or directory with the normalized name already exists in the parent directory. For files, normalizeFileName appends the fallback extension (e.g., '.sql'), so creating 'query' twice produces 'query.sql' both times and hits this guard.

Common situations: User creates a file with the same name as an existing one; the tree view is stale and does not show the already-existing entry; rapid double-submit of the same create action.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/5db5453946f916af. Report an issue: GitHub.