louislam/dockge · error · ValidationError
Compose YAML must be a string
Error message
Compose YAML must be a string
What it means
ValidationError from saveStack: the composeYAML argument must be a string because it is written verbatim to the stack's compose.yaml file. Non-string values (objects produced by YAML editors, null, undefined) are rejected before any file I/O.
Source
Thrown at backend/agent-socket-handlers/docker-socket-handler.ts:342
checkLogin(socket);
const dockerNetworkList = await server.getDockerNetworkList();
callbackResult({
ok: true,
dockerNetworkList,
}, callback);
} catch (e) {
callbackError(e, callback);
}
});
}
async saveStack(server : DockgeServer, name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown) : Promise<Stack> {
// Check types
if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string");
}
if (typeof(composeYAML) !== "string") {
throw new ValidationError("Compose YAML must be a string");
}
if (typeof(composeENV) !== "string") {
throw new ValidationError("Compose ENV must be a string");
}
if (typeof(isAdd) !== "boolean") {
throw new ValidationError("isAdd must be a boolean");
}
const stack = new Stack(server, name, composeYAML, composeENV, false);
await stack.save(isAdd);
return stack;
}
}
View on GitHub (pinned to f809ae192b)
Solutions
- Send the raw YAML text (editor.getValue()) not the editor instance or parsed object
- Default to an empty string '' or a minimal compose template when no YAML exists
- Validate typeof yaml === 'string' before emitting
- Never run the YAML through a parser before sending — the server expects source text
Example fix
// before
socket.emit("create", name, YAML.parse(editorContent), env, isAdd, cb); // object
// after
socket.emit("create", name, editorContent, env, isAdd, cb); // raw string Defensive patterns
Strategy: validation
Validate before calling
function assertComposeYAML(yaml: unknown): asserts yaml is string {
if (typeof yaml !== "string") throw new TypeError("composeYAML must be raw YAML text, not a parsed object");
} Type guard
const isYamlString = (v: unknown): v is string => typeof v === "string";
Try / catch
try {
assertComposeYAML(editorContent);
socket.emit("create", name, editorContent, env, isAdd, cb);
} catch (e) { showError((e as Error).message); } Prevention
- Use editor.getValue() to send raw text, never the editor instance or parsed YAML
- Initialize the YAML editor with '' or a template, not undefined
- Do not YAML.parse payloads before sending them to Dockge
When it happens
Trigger: Emitting 'create'/'stack' with composeYAML as null (editor failed to serialize), an object (parsed YAML sent instead of raw text), or undefined when the YAML pane never initialized.
Common situations: Sending CodeMirror/monaco editor state object instead of its string content; YAML parsed client-side with js-yaml before sending; fresh-stack creation with no default YAML string.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Stack name and service name must be strings
- Invalid stackName or serviceName
- Compose ENV must be a string
- isAdd must be a boolean
- Terminal name must be a string.
AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31).
Data as JSON: /api/errors/e067b4161bf51903.
Report an issue: GitHub.