slopus/happy · error · TmuxSessionIdentifierError

Invalid window name: "${params.window}"

Error message

Invalid window name: "${params.window}"

What it means

Same validator as the session check: when params.window is provided it must match /^[a-zA-Z0-9._-]+$/. An empty or invalid window string (spaces, ':', '*', etc.) throws TmuxSessionIdentifierError to prevent malformed tmux target strings.

Source

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

        };
    }
}

/**
 * Build a tmux session identifier with validation
 */
export function buildTmuxSessionIdentifier(params: {
    session: string;
    window?: string;
    pane?: string;
}): { success: boolean; identifier?: string; error?: string } {
    try {
        if (!params.session || !/^[a-zA-Z0-9._-]+$/.test(params.session)) {
            throw new TmuxSessionIdentifierError(`Invalid session name: "${params.session}"`);
        }

        if (params.window && !/^[a-zA-Z0-9._-]+$/.test(params.window)) {
            throw new TmuxSessionIdentifierError(`Invalid window name: "${params.window}"`);
        }

        if (params.pane && !/^[0-9]+$/.test(params.pane)) {
            throw new TmuxSessionIdentifierError(`Invalid pane identifier: "${params.pane}"`);
        }

        const identifier: TmuxSessionIdentifier = params;
        return {
            success: true,
            identifier: formatTmuxSessionIdentifier(identifier)
        };
    } catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : 'Unknown error'
        };
    }
}

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Sanitize the window name with .replace(/[^a-zA-Z0-9._-]/g, '-').
  2. Omit params.window entirely if you do not mean to target a window (undefined passes validation).
  3. Pre-validate with /^[a-zA-Z0-9._-]+$/ before the call.
  4. Split 'session:window' strings properly instead of putting the combined value in window.

Example fix

// before
validateIdentifier({ session: 'dev', window: 'main win' });
// after
validateIdentifier({ session: 'dev', window: 'main-win' });
Defensive patterns

Strategy: validation

Validate before calling

function assertValidWindow(w) {
  if (w !== undefined && !/^[a-zA-Z0-9._-]+$/.test(w)) {
    throw new Error(`Invalid window name: ${JSON.stringify(w)}`);
  }
}
assertValidWindow(params.window);

Type guard

function isValidWindowName(w) {
  return w === undefined || (typeof w === 'string' && /^[a-zA-Z0-9._-]+$/.test(w));
}

Try / catch

try {
  const res = validateIdentifier({ ...params, window: sanitizedWindow });
} catch (e) {
  if (e instanceof TmuxSessionIdentifierError && /window/.test(e.message)) {
    return { success: false, error: 'Window names may only contain letters, digits, dot, underscore, dash' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the validator with a window value like 'win dow', 'win:0', '', or a glob such as '*'. Note the check is skipped when window is undefined — only present-but-invalid values throw.

Common situations: Constructing targets from user input containing spaces; joining 'session:window' into one field and having part land in window; template placeholders not substituted (e.g. '${window}').

Related errors


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