slopus/happy · error · TmuxSessionIdentifierError

Invalid session identifier: missing session name

Error message

Invalid session identifier: missing session name

What it means

After splitting the identifier on ':', parseTmuxSessionIdentifier requires the first segment (the tmux session name) to be non-empty. An identifier like ':0.0' or ':window' has no session part, which tmux cannot resolve, so this TmuxSessionIdentifierError is thrown.

Source

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

/** Validation error for tmux session identifiers */
export class TmuxSessionIdentifierError extends Error {
    constructor(message: string) {
        super(message);
        this.name = 'TmuxSessionIdentifierError';
    }
}

// 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.`);
        }

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Include the session name before the colon: 'happy:0.0' instead of ':0.0'.
  2. Fix the interpolation source so the session variable is populated.
  3. If only a window is known, use formatTmuxSessionIdentifier with an explicit session field.
  4. Pre-validate with a regex like /^[^:]+/ before parsing.

Example fix

// before
parseTmuxSessionIdentifier(':0.0'); // throws
// after
parseTmuxSessionIdentifier('happy:0.0');
Defensive patterns

Strategy: validation

Validate before calling

const m = /^[^:]+/.exec(identifier);
if (!m || !m[0].trim()) throw new Error('identifier must start with a session name');
parseTmuxSessionIdentifier(identifier);

Type guard

function hasSessionName(id: string): boolean {
  return /^[^:]+/.test(id);
}

Try / catch

try {
  return parseTmuxSessionIdentifier(identifier);
} catch (err) {
  if (err instanceof TmuxSessionIdentifierError) {
    throw new Error(`Bad tmux target '${identifier}': use 'session[:window[.pane]]'`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling parseTmuxSessionIdentifier with a string whose pre-colon segment is empty or whitespace, e.g. ':0.0', ':main', or a template like `${missingVar}:0` where the variable is empty.

Common situations: String interpolation of an unset session variable into an identifier; manually copying a target string from tmux output but dropping the session prefix; storing only the window part and prefixing ':' by mistake.

Related errors


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