slopus/happy · error · TmuxSessionIdentifierError
Invalid window name: "${result.window}". Only alphanumeric c
Error message
Invalid window name: "${result.window}". Only alphanumeric characters, dots, hyphens, and underscores are allowed. What it means
When the identifier includes a window ('session:window'), parseTmuxSessionIdentifier validates the window segment against /^[a-zA-Z0-9._-]+$/ and throws this TmuxSessionIdentifierError if it contains other characters. Window names with spaces or special chars would break tmux target resolution.
Source
Thrown at packages/happy-cli/src/utils/tmux.ts:148
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.`);
}
}
}
return result;
}
// Helper to format tmux session identifier to string
export function formatTmuxSessionIdentifier(identifier: TmuxSessionIdentifier): string {
if (!identifier.session) {
throw new TmuxSessionIdentifierError('Session identifier must have a session name');
}View on GitHub (pinned to b824cd0a46)
Solutions
- Rename the tmux window to a charset-safe name (tmux rename-window).
- Omit the window part and use just the session: 'happy'.
- Sanitize the window segment before composing the identifier string.
- Catch the error and re-resolve the window via tmux list-windows.
Example fix
// before
parseTmuxSessionIdentifier('happy:vim ~/notes.md'); // throws
// after
parseTmuxSessionIdentifier('happy:editor'); // renamed window Defensive patterns
Strategy: validation
Validate before calling
const SAFE = /^[a-zA-Z0-9._-]+$/;
const [session, rest] = identifier.split(':');
const window = rest?.split('.')[0];
if (window && !SAFE.test(window)) throw new Error(`Window '${window}' must match [a-zA-Z0-9._-]+`);
parseTmuxSessionIdentifier(identifier); Type guard
function isSafeWindowSegment(win: string | undefined): boolean {
return win === undefined || /^[a-zA-Z0-9._-]+$/.test(win);
} Try / catch
try {
return parseTmuxSessionIdentifier(identifier);
} catch (err) {
if (err instanceof TmuxSessionIdentifierError && /window name/.test(err.message)) {
return parseTmuxSessionIdentifier(identifier.split(':')[0]); // drop window
}
throw err;
} Prevention
- Rename auto-named windows (they often contain spaces from the running command).
- Target by session only when you don't control window names.
- Sanitize labels used as window names before composing targets.
When it happens
Trigger: Calling parseTmuxSessionIdentifier with an identifier like 'happy:my window', 'happy:win dow.0', or a window segment interpolated from an unvalidated label.
Common situations: tmux windows auto-named after running programs (e.g. 'vim ~/notes.md') whose names contain spaces; users renaming windows freely in tmux; using a descriptive window title with punctuation.
Related errors
- Invalid session name: "${result.session}". Only alphanumeric
- Session identifier must be a non-empty string
- Invalid session identifier: missing session name
- Invalid pane identifier: "${result.pane}". Only numeric valu
- Session identifier must have a session name
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/1e2fe36635e29033.
Report an issue: GitHub.