{"record":{"id":"22874c8b975d241a","repo":"affaan-m/ECC","slug":"structured-session-targets-require-a-non-empty-str","errorCode":null,"errorMessage":"Structured session targets require a non-empty string value","messagePattern":"Structured session targets require a non-empty string value","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/session-adapters/registry.js","lineNumber":46,"sourceCode":"    ...sharedOptions,\n    ...(options.adapterOptions && options.adapterOptions[adapterId]\n      ? options.adapterOptions[adapterId]\n      : {})\n  };\n}\n\nfunction createDefaultAdapters(options = {}) {\n  return [\n    createClaudeHistoryAdapter(buildDefaultAdapterOptions(options, 'claude-history')),\n    createDmuxTmuxAdapter(buildDefaultAdapterOptions(options, 'dmux-tmux')),\n    createCodexWorktreeAdapter(buildDefaultAdapterOptions(options, 'codex-worktree')),\n    createOpencodeAdapter(buildDefaultAdapterOptions(options, 'opencode'))\n  ];\n}\n\nfunction coerceTargetValue(value) {\n  if (typeof value !== 'string' || value.trim().length === 0) {\n    throw new Error('Structured session targets require a non-empty string value');\n  }\n\n  return value.trim();\n}\n\nfunction normalizeStructuredTarget(target, context = {}) {\n  if (!target || typeof target !== 'object' || Array.isArray(target)) {\n    return {\n      target,\n      context: { ...context }\n    };\n  }\n\n  const value = coerceTargetValue(target.value);\n  const type = typeof target.type === 'string' ? target.type.trim() : '';\n  if (type.length === 0) {\n    throw new Error('Structured session targets require a non-empty type');\n  }","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/session-adapters/registry.js#L28-L64","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nregistry.select({ type: 'opencode', value: userInput.value }, context); // userInput.value is ''\n\n// after\nconst value = (userInput.value || '').trim();\nif (!value) throw new Error('A session target value is required');\nregistry.select({ type: 'opencode', value }, context);\n// or simply pass a string\nregistry.select(`opencode:${value}`, context);","handlingStrategy":"validation","validationCode":"function coerceStructuredTarget(target) {\n  if (!target || typeof target !== 'object' || Array.isArray(target)) return target;\n  const value = typeof target.value === 'string' ? target.value.trim() : '';\n  if (!value) throw new Error('Structured session target requires a non-empty value');\n  return { ...target, value };\n}\n// then: registry.select(coerceStructuredTarget(target), context);","typeGuard":"function isStructuredTarget(t) {\n  return t !== null && typeof t === 'object' && !Array.isArray(t)\n    && typeof t.value === 'string' && t.value.trim().length > 0;\n}","tryCatchPattern":"try { registry.select(target, context); }\ncatch (err) {\n  if (err.message === 'Structured session targets require a non-empty string value') {\n    // fall back to a plain string target, or surface a friendly UI error\n    throw new Error('Please provide a non-empty session target value.');\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["registry","target-coercion","validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}