louislam/dockge · warning · ValidationError
Stack not found
Error message
Stack not found
What it means
Dockge throws this ValidationError from Stack.save() when UPDATING an existing stack (isAdd=false) but the stack's directory does not exist on disk. The update path assumes the folder is present to write compose.yaml into it.
Source
Thrown at backend/stack.ts:193
* 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);
}
}
async deploy(socket : DockgeSocket) : Promise<number> {
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", this.getComposeOptions("up", "-d", "--remove-orphans"), this.path);
if (exitCode !== 0) {
throw new Error("Failed to deploy, please check the terminal output for more information.");View on GitHub (pinned to f809ae192b)
Solutions
- Refresh the stack list in the UI and re-open/recreate the stack (the folder is gone)
- Check the stacks directory on the connected agent (default ./data/stacks/<name>) and restore the folder if it was deleted accidentally
- Verify you are connected to the correct agent endpoint where the stack actually lives
- If the stack should be created instead, re-add it with isAdd=true
Example fix
// before
await stack.save(socket, false); // may throw 'Stack not found'
// after
const dir = path.join(stacksDir, name);
if (!fs.existsSync(path.join(dir, 'compose.yaml'))) {
throw new Error(`Stack '${name}' no longer exists; refresh and recreate it`);
}
await stack.save(socket, false); Defensive patterns
Strategy: validation
Validate before calling
import { fileExists } from "./util-common";
async function assertStackDirExists(dir: string) {
if (!(await fileExists(dir))) {
throw new Error(`Stack folder missing: ${dir} — refresh and recreate`);
}
}
await assertStackDirExists(path.join(stacksDir, name));
await stack.save(socket, false); Type guard
function stackExists(list: Stack[], name: string): boolean {
return list.some(s => s.name === name);
} Try / catch
try {
await stack.save(socket, false);
} catch (e) {
if (e instanceof ValidationError && e.message === "Stack not found") {
// refresh stack list / re-create stack with isAdd=true
} else { throw e; }
} Prevention
- Refresh the UI before saving after external folder changes
- Don't delete stack folders manually while the UI is open
- Use volume persistence for the stacks directory on agents
- Verify endpoint/agent selection when managing multi-host setups
When it happens
Trigger: Calling saveStack with isAdd=false for a stack whose directory was deleted externally (manual rm, volume remount, another agent's cleanup) while the UI still had it open.
Common situations: Two browser tabs — one deletes the stack while the other saves; host disk/volume recreated in a container losing the stacks dir; editing a stack that was removed via docker compose down + folder rm; wrong agent/endpoint selected so the folder isn't there.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Stack name already exists
- Name must be a string
- Stack name must be a string
- Stack name and service name must be strings
- Invalid stackName or serviceName
AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31).
Data as JSON: /api/errors/163a1711cf2144fb.
Report an issue: GitHub.