{"record":{"id":"1e2fe36635e29033","repo":"slopus/happy","slug":"invalid-window-name-result-window-only-alph","errorCode":null,"errorMessage":"Invalid window name: \"${result.window}\". Only alphanumeric characters, dots, hyphens, and underscores are allowed.","messagePattern":"Invalid window name: \"(.+?)\"\\. Only alphanumeric characters, dots, hyphens, and underscores are allowed\\.","errorType":"validation","errorClass":"TmuxSessionIdentifierError","httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/utils/tmux.ts","lineNumber":148,"sourceCode":"    if (parts.length === 0 || !parts[0]) {\n        throw new TmuxSessionIdentifierError('Invalid session identifier: missing session name');\n    }\n\n    const result: TmuxSessionIdentifier = {\n        session: parts[0].trim()\n    };\n\n    // Validate session name (tmux has restrictions on session names)\n    if (!/^[a-zA-Z0-9._-]+$/.test(result.session)) {\n        throw new TmuxSessionIdentifierError(`Invalid session name: \"${result.session}\". Only alphanumeric characters, dots, hyphens, and underscores are allowed.`);\n    }\n\n    if (parts.length > 1) {\n        const windowAndPane = parts[1].split('.');\n        result.window = windowAndPane[0]?.trim();\n\n        if (result.window && !/^[a-zA-Z0-9._-]+$/.test(result.window)) {\n            throw new TmuxSessionIdentifierError(`Invalid window name: \"${result.window}\". Only alphanumeric characters, dots, hyphens, and underscores are allowed.`);\n        }\n\n        if (windowAndPane.length > 1) {\n            result.pane = windowAndPane[1]?.trim();\n            if (result.pane && !/^[0-9]+$/.test(result.pane)) {\n                throw new TmuxSessionIdentifierError(`Invalid pane identifier: \"${result.pane}\". Only numeric values are allowed.`);\n            }\n        }\n    }\n\n    return result;\n}\n\n// Helper to format tmux session identifier to string\nexport function formatTmuxSessionIdentifier(identifier: TmuxSessionIdentifier): string {\n    if (!identifier.session) {\n        throw new TmuxSessionIdentifierError('Session identifier must have a session name');\n    }","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/utils/tmux.ts#L130-L166","documentation":"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.","triggerScenarios":"Calling parseTmuxSessionIdentifier with an identifier like 'happy:my window', 'happy:win dow.0', or a window segment interpolated from an unvalidated label.","commonSituations":"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.","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."],"exampleFix":"// before\nparseTmuxSessionIdentifier('happy:vim ~/notes.md'); // throws\n// after\nparseTmuxSessionIdentifier('happy:editor'); // renamed window","handlingStrategy":"validation","validationCode":"const SAFE = /^[a-zA-Z0-9._-]+$/;\nconst [session, rest] = identifier.split(':');\nconst window = rest?.split('.')[0];\nif (window && !SAFE.test(window)) throw new Error(`Window '${window}' must match [a-zA-Z0-9._-]+`);\nparseTmuxSessionIdentifier(identifier);","typeGuard":"function isSafeWindowSegment(win: string | undefined): boolean {\n  return win === undefined || /^[a-zA-Z0-9._-]+$/.test(win);\n}","tryCatchPattern":"try {\n  return parseTmuxSessionIdentifier(identifier);\n} catch (err) {\n  if (err instanceof TmuxSessionIdentifierError && /window name/.test(err.message)) {\n    return parseTmuxSessionIdentifier(identifier.split(':')[0]); // drop window\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["tmux","validation","naming"],"backgroundTag":"invalid-tmux-session-identifier","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}