slopus/happy · error · TmuxSessionIdentifierError

Invalid session name: "${result.session}". Only alphanumeric

Error message

Invalid session name: "${result.session}". Only alphanumeric characters, dots, hyphens, and underscores are allowed.

What it means

tmux restricts session names to a safe charset; parseTmuxSessionIdentifier enforces /^[a-zA-Z0-9._-]+$/ on the parsed session segment and throws this TmuxSessionIdentifierError when the name contains spaces, colons, or other special characters. This prevents commands built from the identifier being misinterpreted or failing inside tmux.

Source

Thrown at packages/happy-cli/src/utils/tmux.ts:140

// Helper to parse tmux session identifier from string with validation
export function parseTmuxSessionIdentifier(identifier: string): TmuxSessionIdentifier {
    if (!identifier || typeof identifier !== 'string') {
        throw new TmuxSessionIdentifierError('Session identifier must be a non-empty string');
    }

    // Format: session:window or session:window.pane or just session
    const parts = identifier.split(':');
    if (parts.length === 0 || !parts[0]) {
        throw new TmuxSessionIdentifierError('Invalid session identifier: missing session name');
    }

    const result: TmuxSessionIdentifier = {
        session: parts[0].trim()
    };

    // Validate session name (tmux has restrictions on session names)
    if (!/^[a-zA-Z0-9._-]+$/.test(result.session)) {
        throw new TmuxSessionIdentifierError(`Invalid session name: "${result.session}". Only alphanumeric characters, dots, hyphens, and underscores are allowed.`);
    }

    if (parts.length > 1) {
        const windowAndPane = parts[1].split('.');
        result.window = windowAndPane[0]?.trim();

        if (result.window && !/^[a-zA-Z0-9._-]+$/.test(result.window)) {
            throw new TmuxSessionIdentifierError(`Invalid window name: "${result.window}". Only alphanumeric characters, dots, hyphens, and underscores are allowed.`);
        }

        if (windowAndPane.length > 1) {
            result.pane = windowAndPane[1]?.trim();
            if (result.pane && !/^[0-9]+$/.test(result.pane)) {
                throw new TmuxSessionIdentifierError(`Invalid pane identifier: "${result.pane}". Only numeric values are allowed.`);
            }
        }
    }

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Rename the tmux session to use only alphanumerics, dots, hyphens, underscores (tmux rename-session).
  2. Sanitize the name before building the identifier: replace invalid chars with '-' or '_'.
  3. Use formatTmuxSessionIdentifier with an already-validated session value.
  4. Catch TmuxSessionIdentifierError and prompt the user for a valid name.

Example fix

// before
parseTmuxSessionIdentifier('my project:0.0'); // throws (space)
// after
const session = rawName.replace(/[^a-zA-Z0-9._-]/g, '_');
parseTmuxSessionIdentifier(`${session}:0.0`);
Defensive patterns

Strategy: validation

Validate before calling

const SAFE = /^[a-zA-Z0-9._-]+$/;
if (!SAFE.test(sessionName)) {
  throw new Error(`Session name '${sessionName}' must match [a-zA-Z0-9._-]+`);
}
parseTmuxSessionIdentifier(`${sessionName}:0.0`);

Type guard

function isSafeTmuxName(name: string): boolean {
  return /^[a-zA-Z0-9._-]+$/.test(name);
}

Try / catch

try {
  return parseTmuxSessionIdentifier(identifier);
} catch (err) {
  if (err instanceof TmuxSessionIdentifierError && /session name/.test(err.message)) {
    return parseTmuxSessionIdentifier(`${sanitize(raw)}:0.0`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Parsing an identifier whose session name contains illegal characters, e.g. 'my session', 'happy:dev:extra', 'project$', or a path-like name 'a/b'.

Common situations: Users naming tmux sessions with spaces; deriving the session name from a directory path or branch name with slashes; pasting a full tmux target containing extra colons; machine/hostnames with underscores-plus-unicode in the name.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/9adb49720df11773. Report an issue: GitHub.