affaan-m/ECC · error · Error
Structured session targets require a non-empty type
Error message
Structured session targets require a non-empty type
What it means
Thrown by normalizeStructuredTarget in the session-adapter registry when a target is passed as an object (structured form) but its `type` field is missing, empty, or not a string. The type is required because TARGET_TYPE_TO_ADAPTER_ID maps it (plan, session, claude-history, claude-alias, session-file, codex-worktree, codex, opencode) to the adapter that should open the session.
Source
Thrown at scripts/lib/session-adapters/registry.js:63
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');
}
const adapterId = target.adapterId || TARGET_TYPE_TO_ADAPTER_ID[type] || context.adapterId || null;
const nextContext = {
...context,
adapterId
};
if (type === 'claude-history' || type === 'claude-alias') {
return {
target: `claude:${value}`,
context: nextContext
};
}
if (type === 'codex-worktree' || type === 'codex') {
return {
target: `codex:${value}`,View on GitHub (pinned to 01e15490f0)
Solutions
- Add a non-empty `type` string from the supported set: plan, session, claude-history, claude-alias, session-file, codex-worktree, codex, or opencode.
- If the target is a plain string (e.g. 'claude:alias' or 'tmux:plan-name'), pass it directly — strings skip structured normalization entirely.
- Remember `type` is validated before `adapterId` is used, so setting adapterId alone is not enough; you still need a type on structured targets.
Example fix
// before
registry.open({ value: 'proj-session' });
// throws: Structured session targets require a non-empty type
// after
registry.open({ type: 'session', value: 'proj-session' }); Defensive patterns
Strategy: validation
Validate before calling
const VALID_TYPES = new Set(['plan','session','claude-history','claude-alias','session-file','codex-worktree','codex','opencode']);
function assertStructuredTarget(t) {
if (t && typeof t === 'object' && !Array.isArray(t)) {
if (typeof t.type !== 'string' || t.type.trim().length === 0) {
throw new TypeError('target.type missing');
}
if (!VALID_TYPES.has(t.type.trim())) {
console.warn('unknown target type:', t.type);
}
}
} Type guard
function isStructuredTarget(t) {
return t != null && typeof t === 'object' && !Array.isArray(t)
&& typeof t.type === 'string' && t.type.trim().length > 0;
} Try / catch
try {
registry.open(target);
} catch (err) {
if (/non-empty type/.test(err.message)) { /* fix target.type */ }
else throw err;
} Prevention
- Prefer plain string targets ('claude:alias') when you don't need structured fields — they skip type validation.
- Keep a single factory that builds structured targets so the type is always set.
- Unit-test the target builder against the VALID_TYPES set.
When it happens
Trigger: Calling registry.select/open/normalizeStructuredTarget with `{ value: 'x' }` (no type), `{ value: 'x', type: ' ' }` (whitespace-only), or `{ value: 'x', type: 123 }` (non-string). Note the value field is checked first by coerceTargetValue, so a missing value throws a different error before this one.
Common situations: Building a structured target programmatically and forgetting the `type` key; renaming `type` to `kind`/`category`; passing a half-built config object; copy-pasting a target literal from docs that omitted type.
Related errors
- Unknown session adapter: ${id}
- ECC_PROJECT_DIR must be a child path within /workspace.
- Unknown argument: ${arg}
- Unable to infer ECC repo root from install-state operations
- Invalid ECC repo root: missing package.json at ${packageJson
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/1a63bbc339ca493f.
Report an issue: GitHub.