{"record":{"id":"f49ad334f0814bd0","repo":"louislam/dockge","slug":"stack-name-already-exists","errorCode":null,"errorMessage":"Stack name already exists","messagePattern":"Stack name already exists","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"warning","filePath":"backend/stack.ts","lineNumber":186,"sourceCode":"        } else {\n            fullPathDir = dir;\n        }\n        return fullPathDir;\n    }\n\n    /**\n     * Save the stack to the disk\n     * @param isAdd\n     */\n    async save(isAdd : boolean) {\n        this.validate();\n\n        let dir = this.path;\n\n        // Check if the name is used if isAdd\n        if (isAdd) {\n            if (await fileExists(dir)) {\n                throw new ValidationError(\"Stack name already exists\");\n            }\n\n            // Create the stack folder\n            await fsAsync.mkdir(dir);\n        } else {\n            if (!await fileExists(dir)) {\n                throw new ValidationError(\"Stack not found\");\n            }\n        }\n\n        // Write or overwrite the compose.yaml\n        fs.writeFileSync(path.join(dir, this._composeFileName), this.composeYAML);\n        if (process.env.PUID && process.env.PGID) {\n            const uid = Number(process.env.PUID);\n            const gid = Number(process.env.PGID);\n            fs.lchownSync(dir, uid, gid);\n            fs.chownSync(path.join(dir, this._composeFileName), uid, gid);\n        }","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/stack.ts#L168-L204","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Pick a different stack name in the UI before saving","Check for an existing folder in the stacks directory (default ./data/stacks/<name>) and remove or rename it if it is a leftover","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","Verify the correct agent/endpoint is connected — the name may only exist on that agent"],"exampleFix":"// before\nconst stack = new Stack(server, name, isAdd, composeYAML);\nawait stack.save(socket, isAdd);\n// after\nconst dir = path.join(stacksDir, name);\nif (isAdd && await fs.existsSync(dir)) {\n    throw new Error(`Stack '${name}' already exists; choose another name or edit the existing stack`);\n}\nawait stack.save(socket, isAdd);","handlingStrategy":"validation","validationCode":"import { fileExists } from \"./util-common\";\nasync function assertNameFree(dir: string) {\n    if (await fileExists(dir)) {\n        throw new Error(`Stack name already used: ${dir} — pick another name`);\n    }\n}\nawait assertNameFree(path.join(stacksDir, desiredName));\nawait stack.save(socket, true);","typeGuard":"function isStackNameAvailable(names: string[], name: string): boolean {\n    return !names.some(n => n === name);\n}","tryCatchPattern":"try {\n    await stack.save(socket, true);\n} catch (e) {\n    if (e instanceof ValidationError && e.message === \"Stack name already exists\") {\n        // prompt user for a different name\n    } else { throw e; }\n}","preventionTips":["Check the stacks directory for name collisions before creating","Keep names filesystem-safe (no spaces/special chars, consistent casing)","After docker-only deletion, clean the leftover stack folder","Confirm you are on the intended agent endpoint before creating"],"tags":["validation","filesystem","stack-management"],"backgroundTag":"stack-name-collision","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}