{"record":{"id":"ea3d39530b608abc","repo":"slopus/happy","slug":"session-identifier-must-have-a-session-name","errorCode":null,"errorMessage":"Session identifier must have a session name","messagePattern":"Session identifier must have a session name","errorType":"exception","errorClass":"TmuxSessionIdentifierError","httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/utils/tmux.ts","lineNumber":165,"sourceCode":"        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    }\n\n    let result = identifier.session;\n    if (identifier.window) {\n        result += `:${identifier.window}`;\n        if (identifier.pane) {\n            result += `.${identifier.pane}`;\n        }\n    }\n    return result;\n}\n\n// Helper to extract session and window from tmux output with improved validation\nexport function extractSessionAndWindow(tmuxOutput: string): { session: string; window: string } | null {\n    if (!tmuxOutput || typeof tmuxOutput !== 'string') {\n        return null;\n    }\n","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/utils/tmux.ts#L147-L183","documentation":"formatTmuxSessionIdentifier converts a TmuxSessionIdentifier object back into a 'session:window.pane' string and requires the session field to be a non-empty string. If identifier.session is missing, null, or empty, it throws this TmuxSessionIdentifierError because the resulting target string would be invalid.","triggerScenarios":"Calling formatTmuxSessionIdentifier({} ), { session: '' }, { window: '0' } — building the object dynamically where the session field was never assigned, or spreading a partial object returned by an earlier failed parse.","commonSituations":"Constructing the identifier from optional config fields where session defaulted to undefined; persisting/restoring a serialized identifier that lost its session key; programmatically building targets from list output that lacked a session name.","solutions":["Always set session before formatting: { session: 'happy', window: '0' }.","Apply a default when the source value is empty: session ?? 'happy'.","Check the object with a type guard before calling format.","Catch TmuxSessionIdentifierError and re-create the identifier from defaults."],"exampleFix":"// before\nformatTmuxSessionIdentifier({ window: '0' }); // throws\n// after\nformatTmuxSessionIdentifier({ session: activeSession ?? 'happy', window: '0' });","handlingStrategy":"type-guard","validationCode":"function canFormatTmuxIdentifier(id: TmuxSessionIdentifier): boolean {\n  return typeof id.session === 'string' && id.session.length > 0;\n}\nif (!canFormatTmuxIdentifier(id)) throw new Error('session required before formatting');\nformatTmuxSessionIdentifier(id);","typeGuard":"function hasSession(id: TmuxSessionIdentifier): id is TmuxSessionIdentifier & { session: string } {\n  return typeof id.session === 'string' && id.session.length > 0;\n}","tryCatchPattern":"try {\n  return formatTmuxSessionIdentifier(id);\n} catch (err) {\n  if (err instanceof TmuxSessionIdentifierError) {\n    return formatTmuxSessionIdentifier({ ...id, session: id.session || 'happy' });\n  }\n  throw err;\n}","preventionTips":["Type identifiers as TmuxSessionIdentifier with a required session field, not loose objects.","Apply defaults (session ?? 'happy') at construction time.","Validate serialized identifiers on load before re-formatting."],"tags":["tmux","validation","types"],"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"}