{"record":{"id":"19e8196a3ac3f197","repo":"affaan-m/ECC","slug":"assigneekind-must-be-agent-or-human","errorCode":null,"errorMessage":"assigneeKind must be 'agent' or 'human'.","messagePattern":"assigneeKind must be 'agent' or 'human'\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/control-pane/work-item-mutations.js","lineNumber":62,"sourceCode":"    }\n    return item;\n  }\n  const { items } = store.listWorkItems({ limit: 100 });\n  return items.filter(item => !item.owner && isOpenStatus(item.status)).sort((a, b) => priorityRank(a.priority) - priorityRank(b.priority))[0] || null;\n}\n\n/**\n * Claim an unassigned work item for an agent or human. Sets the owner (and\n * optional assigneeKind) and moves the card to running unless an explicit\n * status is supplied. Returns { claimed, item } or { claimed: false, reason }.\n */\nfunction claimWorkItem(store, { id, owner, assigneeKind, sessionId, status } = {}) {\n  if (!owner) {\n    throw new Error('claim requires an owner.');\n  }\n  const kind = assigneeKind ? String(assigneeKind).toLowerCase() : null;\n  if (kind && !VALID_ASSIGNEE_KINDS.has(kind)) {\n    throw new Error(\"assigneeKind must be 'agent' or 'human'.\");\n  }\n  const target = selectClaimTarget(store, { id });\n  if (!target) {\n    return { claimed: false, reason: 'no-unassigned-open-items' };\n  }\n  if (!isOpenStatus(target.status)) {\n    throw new Error(`Work item ${target.id} is already done; cannot claim.`);\n  }\n  const metadata = { ...(target.metadata || {}) };\n  if (kind) {\n    metadata.assigneeKind = kind;\n  }\n  const item = store.upsertWorkItem({\n    ...target,\n    owner,\n    sessionId: sessionId ?? target.sessionId ?? null,\n    status: status ?? 'running',\n    metadata,","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/control-pane/work-item-mutations.js#L44-L80","documentation":"Thrown by claimWorkItem when assigneeKind is provided but is not one of VALID_ASSIGNEE_KINDS ('agent' or 'human'). The kind is lowercased before checking, so case differences are tolerated, but any other value (e.g. 'bot', 'system', 'auto') is rejected because the board only distinguishes the two kinds. Leaving assigneeKind undefined is allowed and skips the metadata tag.","triggerScenarios":"Passing assigneeKind: 'bot' or 'system'; passing a value from an external system that uses different role names; a typo like 'agents' or 'Human ' with trailing space (trim is applied to lane but the kind check uses the lowercased value without trim — note the code does String(assigneeKind).toLowerCase() but NOT trim).","commonSituations":"Integrating an external tracker whose role taxonomy differs; user-typed kind in a CLI/UI; copied config from another tool.","solutions":["Pass only 'agent', 'human', or undefined/omitted for assigneeKind.","Map external role names to one of the two valid values before calling claimWorkItem.","If a new kind is genuinely needed, extend VALID_ASSIGNEE_KINDS in work-item-mutations.js and update the board rendering.","Validate at the call site: const kind = ['agent','human'].includes(String(raw).toLowerCase()) ? String(raw).toLowerCase() : undefined."],"exampleFix":"// before\nclaimWorkItem(store, { id, owner, assigneeKind: role }); // role may be 'bot'\n\n// after — coerce to a valid kind or omit\nconst raw = String(role || '').trim().toLowerCase();\nconst assigneeKind = raw === 'agent' || raw === 'human' ? raw : undefined;\nclaimWorkItem(store, { id, owner, assigneeKind });","handlingStrategy":"type-guard","validationCode":"const raw = String(assigneeKind || '').trim().toLowerCase();\nif (raw && raw !== 'agent' && raw !== 'human') {\n  throw new Error(`assigneeKind must be 'agent' or 'human', got ${assigneeKind}`);\n}","typeGuard":"function isValidAssigneeKind(kind) {\n  const k = String(kind || '').trim().toLowerCase();\n  return k === '' || k === 'agent' || k === 'human';\n}","tryCatchPattern":"try {\n  claimWorkItem(store, { id, owner, assigneeKind });\n} catch (e) {\n  if (/assigneeKind must be/.test(e.message)) { claimWorkItem(store, { id, owner }); return; }\n  throw e;\n}","preventionTips":["Map external role names to 'agent' or 'human' before calling.","Omit assigneeKind entirely when unsure rather than guessing.","Extend VALID_ASSIGNEE_KINDS only if a new kind is a real product requirement."],"tags":["work-items","claim","validation","enum"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}