louislam/dockge · error · Error

Terminal name must be a string.

Error message

Terminal name must be a string.

What it means

Thrown by the 'terminalInput' handler in TerminalSocketHandler when the terminalName argument is not a string. Terminal names are used to look up the active terminal map, so the handler validates the type first (then validates that cmd is a string too).

Source

Thrown at backend/agent-socket-handlers/terminal-socket-handler.ts:17

import { DockgeServer } from "../dockge-server";
import { callbackError, callbackResult, checkLogin, DockgeSocket, ValidationError } from "../util-server";
import { log } from "../log";
import { InteractiveTerminal, MainTerminal, Terminal } from "../terminal";
import { Stack } from "../stack";
import { AgentSocketHandler } from "../agent-socket-handler";
import { AgentSocket } from "../../common/agent-socket";

export class TerminalSocketHandler extends AgentSocketHandler {
    create(socket : DockgeSocket, server : DockgeServer, agentSocket : AgentSocket) {

        agentSocket.on("terminalInput", async (terminalName : unknown, cmd : unknown, callback) => {
            try {
                checkLogin(socket);

                if (typeof(terminalName) !== "string") {
                    throw new Error("Terminal name must be a string.");
                }

                if (typeof(cmd) !== "string") {
                    throw new Error("Command must be a string.");
                }

                let terminal = Terminal.getTerminal(terminalName);
                if (terminal instanceof InteractiveTerminal) {
                    //log.debug("terminalInput", "Terminal found, writing to terminal.");
                    terminal.write(cmd);
                } else {
                    throw new Error("Terminal not found or it is not a Interactive Terminal.");
                }
            } catch (e) {
                callbackError(e, callback);
            }
        });

View on GitHub (pinned to f809ae192b)

Solutions

  1. Pass the registered terminal name string (e.g. the combined terminal name) exactly as attached
  2. Only emit input after the terminal is attached and its name is known
  3. Validate typeof terminalName === 'string' before emitting
  4. If you hold a terminal object, send its name property, not the object

Example fix

// before
socket.emit("terminalInput", terminal, cmd, cb); // object
// after
socket.emit("terminalInput", terminalName, cmd, cb); // string name
Defensive patterns

Strategy: type-guard

Validate before calling

function assertTerminalInput(terminalName: unknown, cmd: unknown): asserts terminalName is string {
  if (typeof terminalName !== "string") throw new TypeError("terminalName must be a string");
  if (typeof cmd !== "string") throw new TypeError("cmd must be a string");
}

Type guard

const isTerminalName = (v: unknown): v is string => typeof v === "string" && v.length > 0;

Try / catch

socket.emit("terminalInput", terminalName, cmd, (res) => {
  if (res && res.ok === false) console.warn("terminalInput rejected:", res.msg);
});

Prevention

When it happens

Trigger: socket.emit('terminalInput', terminalName, cmd) with terminalName undefined (terminal not attached yet), null, or an object (terminal instance passed instead of its name).

Common situations: Terminal component emits input before the connection/handshake assigns the terminal name; passing the xterm.js Terminal object instead of its registered name; automated input scripts with unset variables.

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


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