jackwener/OpenCLI · error

Command ${key} siteSession must be one of: ephemeral, persis

Error message

Command ${key} siteSession must be one of: ephemeral, persistent

What it means

assertSiteSession validates the optional siteSession property on a registered command: when present it must be exactly 'ephemeral' or 'persistent'. These values control how the CLI manages site sessions for the command, so any other value is rejected at registration time via normalizeCommand.

Source

Thrown at src/registry.ts:218

    }
  }

  return browser
    ? { ...cmd, strategy, browser: true, navigateBefore } as BrowserCliCommand
    : { ...cmd, strategy, browser: false, navigateBefore } as NonBrowserCliCommand;
}

function assertCommandAccess(cmd: Pick<RawCliCommand, 'site' | 'name'> & { access?: unknown }): asserts cmd is RawCliCommand {
  if (cmd.access === 'read' || cmd.access === 'write') return;
  const key = `${cmd.site}/${cmd.name}`;
  throw new Error(`Command ${key} must declare access: 'read' | 'write'`);
}

function assertSiteSession(cmd: Pick<RawCliCommand, 'site' | 'name'> & { siteSession?: unknown }): void {
  if (cmd.siteSession === undefined) return;
  const key = `${cmd.site}/${cmd.name}`;
  if (cmd.siteSession !== 'ephemeral' && cmd.siteSession !== 'persistent') {
    throw new Error(`Command ${key} siteSession must be one of: ephemeral, persistent`);
  }
}

export function registerCommand(cmd: RawCliCommand): void {
  const normalized = normalizeCommand(cmd);
  const canonicalKey = fullName(normalized);
  const existing = _registry.get(canonicalKey);
  if (existing?.aliases) {
    for (const alias of existing.aliases) {
      _registry.delete(`${existing.site}/${alias}`);
    }
  }

  const aliases = normalizeAliases(normalized.aliases, normalized.name);
  normalized.aliases = aliases.length > 0 ? aliases : undefined;
  _registry.set(canonicalKey, normalized);
  for (const alias of aliases) {
    _registry.set(`${normalized.site}/${alias}`, normalized);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Set siteSession to exactly 'ephemeral' or 'persistent', or remove the property if no session behavior is needed.
  2. Fix casing — the comparison is strict, 'Ephemeral' fails.
  3. If a different session mode seems needed, check the library docs; only the two values are supported.
  4. Add a schema/config lint step for command definitions to catch invalid enum values before registration.

Example fix

// before
registerCommand({ site: "jira", name: "login", access: "write", siteSession: "temporary" });
// after
registerCommand({ site: "jira", name: "login", access: "write", siteSession: "persistent" });
Defensive patterns

Strategy: type-guard

Validate before calling

type SiteSession = "ephemeral" | "persistent";
function hasValidSiteSession(cmd: { siteSession?: unknown }): boolean {
  return cmd.siteSession === undefined || cmd.siteSession === "ephemeral" || cmd.siteSession === "persistent";
}
if (hasValidSiteSession(cmd)) registerCommand(cmd);

Type guard

function hasSiteSession(cmd: { siteSession?: unknown }): cmd is { siteSession: "ephemeral" | "persistent" } {
  return cmd.siteSession === "ephemeral" || cmd.siteSession === "persistent";
}

Try / catch

try {
  registerCommand(cmd);
} catch (e) {
  if (e instanceof Error && e.message.includes("siteSession must be one of")) {
    console.error(`Bad siteSession on ${cmd.site}/${cmd.name}: use 'ephemeral' or 'persistent'`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling registerCommand(cmd) with cmd.siteSession defined but not 'ephemeral' or 'persistent' — e.g. siteSession: true, 'none', 'temporary', or 'Ephemeral' (case-sensitive). Omitting the property entirely is allowed.

Common situations: Typo or wrong-case value in a new command definition; copying a boolean-ish flag from another config; inventing a third session mode the library doesn't support.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/8b1b849522ac2356. Report an issue: GitHub.