{"record":{"id":"1a63bbc339ca493f","repo":"affaan-m/ECC","slug":"structured-session-targets-require-a-non-empty-typ","errorCode":null,"errorMessage":"Structured session targets require a non-empty type","messagePattern":"Structured session targets require a non-empty type","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/session-adapters/registry.js","lineNumber":63,"sourceCode":"  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  }\n\n  const adapterId = target.adapterId || TARGET_TYPE_TO_ADAPTER_ID[type] || context.adapterId || null;\n  const nextContext = {\n    ...context,\n    adapterId\n  };\n\n  if (type === 'claude-history' || type === 'claude-alias') {\n    return {\n      target: `claude:${value}`,\n      context: nextContext\n    };\n  }\n\n  if (type === 'codex-worktree' || type === 'codex') {\n    return {\n      target: `codex:${value}`,","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/session-adapters/registry.js#L45-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nregistry.open({ value: 'proj-session' });\n// throws: Structured session targets require a non-empty type\n\n// after\nregistry.open({ type: 'session', value: 'proj-session' });","handlingStrategy":"validation","validationCode":"const VALID_TYPES = new Set(['plan','session','claude-history','claude-alias','session-file','codex-worktree','codex','opencode']);\nfunction assertStructuredTarget(t) {\n  if (t && typeof t === 'object' && !Array.isArray(t)) {\n    if (typeof t.type !== 'string' || t.type.trim().length === 0) {\n      throw new TypeError('target.type missing');\n    }\n    if (!VALID_TYPES.has(t.type.trim())) {\n      console.warn('unknown target type:', t.type);\n    }\n  }\n}","typeGuard":"function isStructuredTarget(t) {\n  return t != null && typeof t === 'object' && !Array.isArray(t)\n    && typeof t.type === 'string' && t.type.trim().length > 0;\n}","tryCatchPattern":"try {\n  registry.open(target);\n} catch (err) {\n  if (/non-empty type/.test(err.message)) { /* fix target.type */ }\n  else throw err;\n}","preventionTips":["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."],"tags":["session-adapters","structured-target","validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}