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() inside the adapter registry rejects a structured target whose `value` is not a non-empty string. normalizeStructuredTarget routes object-shaped targets through coerceTargetValue before mapping them to a prefixed target string, so { type: ..., value } must carry a trimmed non-empty value. Non-object targets bypass this check and are returned as-is.
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 01e15490f0)
Solutions
- Validate value before constructing the structured target: if (!value || typeof value !== 'string') throw a clearer error or fall back to a string target.
- Coerce to a trimmed string and reject empty: value = String(value||'').trim(); if (!value) throw new Error('target value required').
- Prefer passing a plain string target (e.g. 'claude:<id>') when you already have the value; structured form is optional.
- In UI/CLI, disable submit until value is non-empty.
Example fix
// before
registry.select({ type: 'opencode', value: userInput.value }, context); // userInput.value is ''
// after
const value = (userInput.value || '').trim();
if (!value) throw new Error('A session target value is required');
registry.select({ type: 'opencode', value }, context);
// or simply pass a string
registry.select(`opencode:${value}`, context); Defensive patterns
Strategy: validation
Validate before calling
function coerceStructuredTarget(target) {
if (!target || typeof target !== 'object' || Array.isArray(target)) return target;
const value = typeof target.value === 'string' ? target.value.trim() : '';
if (!value) throw new Error('Structured session target requires a non-empty value');
return { ...target, value };
}
// then: registry.select(coerceStructuredTarget(target), context); Type guard
function isStructuredTarget(t) {
return t !== null && typeof t === 'object' && !Array.isArray(t)
&& typeof t.value === 'string' && t.value.trim().length > 0;
} Try / catch
try { registry.select(target, context); }
catch (err) {
if (err.message === 'Structured session targets require a non-empty string value') {
// fall back to a plain string target, or surface a friendly UI error
throw new Error('Please provide a non-empty session target value.');
}
throw err;
} Prevention
- Validate target.value at the UI/CLI boundary before constructing the structured target.
- Prefer plain string targets (e.g. 'opencode:<id>') unless you need type metadata.
- Disable submit actions until value is non-empty.
When it happens
Trigger: Calling adapter registry .select() (or open/normalize) with target = { type: 'claude-history', value: '' } or { type: 'opencode', value: null } or { type: 'codex', value: 42 }. Programmatically building a structured target from user input without validating the value field.
Common situations: A CLI form that lets a user pick a target type but leave the value blank. A wrapper that constructs { type, value } from separate inputs where value came back undefined. Migrating from string targets to structured targets and forgetting to default value to an empty string that slips through.
Related errors
- Template name must be a non-empty string
- Template content must be a non-empty string
- ECC_PROJECT_DIR must be a child path within /workspace.
- Unknown argument: ${arg}
- Unable to infer ECC repo root from install-state operations
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/22874c8b975d241a.
Report an issue: GitHub.