louislam/dockge · error · ValidationError
Service name must be a string.
Error message
Service name must be a string.
What it means
Thrown as a ValidationError in the interactiveTerminal handler when the serviceName argument is not a string. Like the other checks in this handler it validates raw socket input before resolving the stack service that will host the shell.
Source
Thrown at backend/agent-socket-handlers/terminal-socket-handler.ts:96
callbackResult({
ok: server.config.enableConsole,
}, callback);
} catch (e) {
callbackError(e, callback);
}
});
// Interactive Terminal for containers
agentSocket.on("interactiveTerminal", async (stackName : unknown, serviceName : unknown, shell : unknown, callback) => {
try {
checkLogin(socket);
if (typeof(stackName) !== "string") {
throw new ValidationError("Stack name must be a string.");
}
if (typeof(serviceName) !== "string") {
throw new ValidationError("Service name must be a string.");
}
if (typeof(shell) !== "string") {
throw new ValidationError("Shell must be a string.");
}
log.debug("interactiveTerminal", "Stack name: " + stackName);
log.debug("interactiveTerminal", "Service name: " + serviceName);
// Get stack
const stack = await Stack.getStack(server, stackName);
stack.joinContainerTerminal(socket, serviceName, shell);
callbackResult({
ok: true,
}, callback);
} catch (e) {
callbackError(e, callback);View on GitHub (pinned to f809ae192b)
Solutions
- Pass the service name as a string, e.g. socket.emit('interactiveTerminal', stackName, service.name, shell, cb).
- Ensure a service is selected/available in the UI before opening the terminal.
- Check stack definition includes services and the client receives them correctly.
- Coerce only after verifying the value is defined (String(serviceName)).
Example fix
// before
socket.emit("interactiveTerminal", stackName, undefined, shell, cb);
// after
const serviceName = selectedService?.name;
if (typeof serviceName === "string") {
socket.emit("interactiveTerminal", stackName, serviceName, shell, cb);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof serviceName !== "string" || serviceName === "") { showError("Select a service"); return; }
socket.emit("interactiveTerminal", stackName, serviceName, shell, cb); Type guard
const isNonEmptyString = (v) => typeof v === "string" && v.length > 0;
Try / catch
socket.emit("interactiveTerminal", stackName, serviceName, shell, (res) => { if (res?.error) showError(res.error.message); }); Prevention
- Require a service selection before opening a terminal.
- Pass service.name, not the service object.
- Check the stack actually has services before rendering the terminal UI.
- Validate emit args centrally in a wrapper.
When it happens
Trigger: Emitting 'interactiveTerminal' with a second argument (serviceName) that is null, undefined, a number, or an object instead of a string.
Common situations: Service dropdown empty (no services in the stack), client passing a service object rather than its name, or a UI bug where no service is chosen before opening the terminal.
Related errors
- Stack name must be a string.
- Shell must be a string.
- Command must be a string.
- Command must be a number.
- Stack name and service name must be strings
AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31).
Data as JSON: /api/errors/7bdea818e240bafc.
Report an issue: GitHub.