louislam/dockge · warning · ValidationError

Stack name already exists

Error message

Stack name already exists

What it means

Dockge throws this ValidationError from Stack.save() when creating a NEW stack (isAdd=true) whose target directory (server stack base dir + stack name) already exists on disk. It prevents silently overwriting an existing stack's compose.yaml. saveStack (the socket route) surfaces it to the UI.

Source

Thrown at backend/stack.ts:186

        } else {
            fullPathDir = dir;
        }
        return fullPathDir;
    }

    /**
     * Save the stack to the disk
     * @param isAdd
     */
    async save(isAdd : boolean) {
        this.validate();

        let dir = this.path;

        // Check if the name is used if isAdd
        if (isAdd) {
            if (await fileExists(dir)) {
                throw new ValidationError("Stack name already exists");
            }

            // Create the stack folder
            await fsAsync.mkdir(dir);
        } else {
            if (!await fileExists(dir)) {
                throw new ValidationError("Stack not found");
            }
        }

        // Write or overwrite the compose.yaml
        fs.writeFileSync(path.join(dir, this._composeFileName), this.composeYAML);
        if (process.env.PUID && process.env.PGID) {
            const uid = Number(process.env.PUID);
            const gid = Number(process.env.PGID);
            fs.lchownSync(dir, uid, gid);
            fs.chownSync(path.join(dir, this._composeFileName), uid, gid);
        }

View on GitHub (pinned to f809ae192b)

Solutions

  1. Pick a different stack name in the UI before saving
  2. Check for an existing folder in the stacks directory (default ./data/stacks/<name>) and remove or rename it if it is a leftover
  3. If the stack was only 'down'ed via Docker and the folder is still wanted, use the existing stack in the UI instead of re-adding
  4. Verify the correct agent/endpoint is connected — the name may only exist on that agent

Example fix

// before
const stack = new Stack(server, name, isAdd, composeYAML);
await stack.save(socket, isAdd);
// after
const dir = path.join(stacksDir, name);
if (isAdd && await fs.existsSync(dir)) {
    throw new Error(`Stack '${name}' already exists; choose another name or edit the existing stack`);
}
await stack.save(socket, isAdd);
Defensive patterns

Strategy: validation

Validate before calling

import { fileExists } from "./util-common";
async function assertNameFree(dir: string) {
    if (await fileExists(dir)) {
        throw new Error(`Stack name already used: ${dir} — pick another name`);
    }
}
await assertNameFree(path.join(stacksDir, desiredName));
await stack.save(socket, true);

Type guard

function isStackNameAvailable(names: string[], name: string): boolean {
    return !names.some(n => n === name);
}

Try / catch

try {
    await stack.save(socket, true);
} catch (e) {
    if (e instanceof ValidationError && e.message === "Stack name already exists") {
        // prompt user for a different name
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling saveStack with isAdd=true when a folder named after the stack already exists in the stacks directory — e.g. creating a stack whose name collides with an existing one, or a leftover directory from a previously deleted stack that was only removed from Docker (docker compose down) but whose folder was kept.

Common situations: Re-adding a stack after renaming; restoring stacks from a volume backup where names collide; creating a stack named the same on two agents but the name exists on the connected agent; case-sensitivity mismatches (Linux FS treats 'MyStack' and 'mystack' as different).

Related errors


AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31). Data as JSON: /api/errors/f49ad334f0814bd0. Report an issue: GitHub.