affaan-m/ECC · error · Error

Unknown session adapter: ${id}

Error message

Unknown session adapter: ${id}

What it means

Thrown by registry.getAdapter(id) when no adapter in the registered `adapters` array has a matching `id`. getAdapter is called directly, and indirectly by select()/open() whenever a target carries an `adapterId` (on the object or in context) that cannot be resolved to a real adapter.

Source

Thrown at scripts/lib/session-adapters/registry.js:107

      context: nextContext
    };
  }

  return {
    target: value,
    context: nextContext
  };
}

function createAdapterRegistry(options = {}) {
  const adapters = options.adapters || createDefaultAdapters(options);

  return {
    adapters,
    getAdapter(id) {
      const adapter = adapters.find(candidate => candidate.id === id);
      if (!adapter) {
        throw new Error(`Unknown session adapter: ${id}`);
      }

      return adapter;
    },
    listAdapters() {
      return adapters.map(adapter => ({
        id: adapter.id,
        description: adapter.description || '',
        targetTypes: Array.isArray(adapter.targetTypes) ? [...adapter.targetTypes] : []
      }));
    },
    select(target, context = {}) {
      const normalized = normalizeStructuredTarget(target, context);
      const adapter = normalized.context.adapterId
        ? this.getAdapter(normalized.context.adapterId)
        : adapters.find(candidate => candidate.canOpen(normalized.target, normalized.context));
      if (!adapter) {
        throw new Error(`No session adapter matched target: ${target}`);

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Use a valid adapter id: claude-history, dmux-tmux, codex-worktree, or opencode (call registry.listAdapters() to confirm).
  2. If you passed options.adapters, either omit it to get createDefaultAdapters(), or include the adapter your target requires.
  3. Fix the typo — ids are kebab-case and exact.

Example fix

// before
registry.select({}, { adapterId: 'tmux' });
// throws: Unknown session adapter: tmux

// after
registry.select({}, { adapterId: 'dmux-tmux' });
Defensive patterns

Strategy: validation

Validate before calling

function resolveAdapterId(registry, id) {
  const valid = new Set(registry.listAdapters().map(a => a.id));
  if (!valid.has(id)) {
    throw new Error(`adapter '${id}' not in: ${[...valid].join(', ')}`);
  }
  return id;
}

Type guard

function isKnownAdapterId(registry, id) {
  return typeof id === 'string' && registry.listAdapters().some(a => a.id === id);
}

Try / catch

try {
  registry.getAdapter(id);
} catch (err) {
  if (/Unknown session adapter/.test(err.message)) {
    id = registry.listAdapters()[0]?.id; // fallback
  } else throw err;
}

Prevention

When it happens

Trigger: Calling registry.getAdapter('foo'); passing `{ adapterId: 'tmux' }` (typo for 'dmux-tmux'); supplying options.adapters as a custom array that omits the default adapters; a target.type that maps via TARGET_TYPE_TO_ADAPTER_ID to an adapter not present in the registry.

Common situations: Typos in adapter id (e.g. 'claude_history' with underscore, 'codex' vs 'codex-worktree'); injecting a filtered/custom adapters list for testing that leaves out the one a target needs; version drift where an adapter was renamed.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/cc57457acf8f9fc3. Report an issue: GitHub.