slopus/happy · error · TmuxSessionIdentifierError

Invalid pane identifier: "${params.pane}"

Error message

Invalid pane identifier: "${params.pane}"

What it means

When params.pane is provided, the validator requires it to be all digits (/^[0-9]+$/) because tmux pane indices are numeric. Non-numeric pane values throw TmuxSessionIdentifierError.

Source

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

/**
 * 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. Pass only the numeric index: pane: '0', not '%0'.
  2. Strip non-digits: pane.replace(/[^0-9]/g, '').
  3. If you have a tmux pane id (e.g. '%3'), resolve it to an index first via display-message -p '#{pane_index}'.
  4. Omit the pane field to target the whole window instead.

Example fix

// before
validateIdentifier({ session: 'dev', window: 'main', pane: '%0' });
// after
validateIdentifier({ session: 'dev', window: 'main', pane: '0' });
Defensive patterns

Strategy: validation

Validate before calling

function assertValidPane(p) {
  if (p !== undefined && !/^[0-9]+$/.test(p)) {
    throw new Error(`Pane must be a numeric index, got: ${JSON.stringify(p)}`);
  }
}
assertValidPane(params.pane);

Type guard

function isValidPaneIndex(p) {
  return p === undefined || (typeof p === 'string' && /^[0-9]+$/.test(p));
}

Try / catch

try {
  const res = validateIdentifier({ ...params, pane: paneIndex });
} catch (e) {
  if (e instanceof TmuxSessionIdentifierError && /pane/.test(e.message)) {
    return { success: false, error: 'Pane must be a numeric index (e.g. "0")' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the validator with pane values like '0%', '%0', 'a', '1.0', or '0 ' — anything present but not purely digits. Omitting pane (undefined) skips the check.

Common situations: Copying tmux target strings like '%3' (pane IDs use a % prefix in tmux display) into the pane field; passing '0.0'; string coercion of a float index; user input with whitespace.

Related errors


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