affaan-m/ECC · error · Error

Structured session targets require a non-empty string value

Error message

Structured session targets require a non-empty string value

What it means

coerceTargetValue in the session adapter registry validates that a structured session target's value is a non-empty string; it throws this when value is not a string, an empty string, or whitespace-only. Structured targets (e.g. { type, value }) must carry a usable string value for the adapter to resolve.

Solutions

  1. Always pass a non-empty string value: String(value) with a trim and length check before building the target.
  2. Fix the config/env source so the value is populated (e.g. default to 'latest').
  3. Coerce numeric ids to strings explicitly (String(id)).
  4. Validate structured targets with a schema (zod/ajv) at the boundary before calling the registry.

Example fix

// before
registry.normalize({ type: 'claude-history', value: process.env.SESSION }); // SESSION unset -> ''
// after
const value = (process.env.SESSION ?? 'latest').trim();
if (!value) throw new Error('SESSION must be a non-empty string');
registry.normalize({ type: 'claude-history', value });
Defensive patterns

Strategy: type-guard

Validate before calling

function assertStructuredTarget(t) {
  if (!t || typeof t !== 'object') throw new Error('Structured target must be an object');
  if (typeof t.value !== 'string' || t.value.trim().length === 0) throw new Error('Structured target.value must be a non-empty string');
}

Type guard

function hasNonEmptyStringValue(t) { return typeof t === 'object' && t !== null && typeof t.value === 'string' && t.value.trim().length > 0; }

Try / catch

try { return registry.normalizeStructuredTarget(target); } catch (e) { if (e.message === 'Structured session targets require a non-empty string value') throw new Error(`Bad target.value=${JSON.stringify(target?.value)}; provide a non-empty string`); throw e; }

Prevention

When it happens

Trigger: Passing a structured target like { type: 'claude-history', value: null } / { value: '' } / { value: 42 } / { value: ' ' } into normalizeStructuredTarget/registry resolution, typically from programmatic callers or JSON config with missing/blank fields.

Common situations: Config files where the target value was left blank; env var unset then interpolated to empty string; JSON deserialization yielding null instead of string; callers passing a numeric id instead of a string.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/22874c8b975d241a. Report an issue: GitHub.

Appendix: source

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

    ...sharedOptions,
    ...(options.adapterOptions && options.adapterOptions[adapterId]
      ? options.adapterOptions[adapterId]
      : {})
  };
}

function createDefaultAdapters(options = {}) {
  return [
    createClaudeHistoryAdapter(buildDefaultAdapterOptions(options, 'claude-history')),
    createDmuxTmuxAdapter(buildDefaultAdapterOptions(options, 'dmux-tmux')),
    createCodexWorktreeAdapter(buildDefaultAdapterOptions(options, 'codex-worktree')),
    createOpencodeAdapter(buildDefaultAdapterOptions(options, 'opencode'))
  ];
}

function coerceTargetValue(value) {
  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new Error('Structured session targets require a non-empty string value');
  }

  return value.trim();
}

function normalizeStructuredTarget(target, context = {}) {
  if (!target || typeof target !== 'object' || Array.isArray(target)) {
    return {
      target,
      context: { ...context }
    };
  }

  const value = coerceTargetValue(target.value);
  const type = typeof target.type === 'string' ? target.type.trim() : '';
  if (type.length === 0) {
    throw new Error('Structured session targets require a non-empty type');
  }

View on GitHub (pinned to 8321021c54)