affaan-m/ECC · error · Error

claim requires an owner.

Error message

claim requires an owner.

What it means

Thrown by claimWorkItem when the owner argument is falsy (undefined, null, empty string). Every claim must attribute the item to an owner (agent name or human name) so the board and audit trail stay accurate; an ownerless claim would leave the card assigned to nobody. This is a precondition failure, not a state problem.

Source

Thrown at scripts/lib/control-pane/work-item-mutations.js:58

  if (id) {
    const item = store.getWorkItemById(id);
    if (!item) {
      throw new Error(`Work item not found: ${id}`);
    }
    return item;
  }
  const { items } = store.listWorkItems({ limit: 100 });
  return items.filter(item => !item.owner && isOpenStatus(item.status)).sort((a, b) => priorityRank(a.priority) - priorityRank(b.priority))[0] || null;
}

/**
 * Claim an unassigned work item for an agent or human. Sets the owner (and
 * optional assigneeKind) and moves the card to running unless an explicit
 * status is supplied. Returns { claimed, item } or { claimed: false, reason }.
 */
function claimWorkItem(store, { id, owner, assigneeKind, sessionId, status } = {}) {
  if (!owner) {
    throw new Error('claim requires an owner.');
  }
  const kind = assigneeKind ? String(assigneeKind).toLowerCase() : null;
  if (kind && !VALID_ASSIGNEE_KINDS.has(kind)) {
    throw new Error("assigneeKind must be 'agent' or 'human'.");
  }
  const target = selectClaimTarget(store, { id });
  if (!target) {
    return { claimed: false, reason: 'no-unassigned-open-items' };
  }
  if (!isOpenStatus(target.status)) {
    throw new Error(`Work item ${target.id} is already done; cannot claim.`);
  }
  const metadata = { ...(target.metadata || {}) };
  if (kind) {
    metadata.assigneeKind = kind;
  }
  const item = store.upsertWorkItem({
    ...target,

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Always pass a non-empty owner string (agent id or human name) when calling claimWorkItem.
  2. In UI/CLI code, validate owner before calling and show a helpful message if empty rather than letting the throw propagate.
  3. For agent callers, derive owner from the session/agent identity so it can never be empty.
  4. Add a unit test asserting claimWorkItem throws on empty owner to lock the contract.

Example fix

// before
claimWorkItem(store, { id, owner: name });

// after — guard at the call site
if (!owner || !owner.trim()) {
  throw new Error('Please provide a non-empty owner name to claim.');
}
claimWorkItem(store, { id, owner: owner.trim() });
Defensive patterns

Strategy: validation

Validate before calling

if (!owner || typeof owner !== 'string' || !owner.trim()) {
  throw new Error('Claim requires a non-empty owner name.');
}

Type guard

function isValidOwner(owner) {
  return typeof owner === 'string' && owner.trim().length > 0;
}

Try / catch

try {
  claimWorkItem(store, { id, owner });
} catch (e) {
  if (/claim requires an owner/.test(e.message)) { promptForOwner(); return; }
  throw e;
}

Prevention

When it happens

Trigger: Calling claimWorkItem({ owner: '' }) or claimWorkItem({ id }) with no owner; a UI prompt (window.prompt) that returned null/empty when the user cancelled or left it blank; a CLI flag --owner that was not passed.

Common situations: User pressed Cancel/Enter on the 'Claim as' prompt (eccClaimItem in ui.js returns early on falsy owner but other callers may not); CLI invocation missing the --owner argument; agent loop forgot to pass its session identity.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/9ab1c9aee89d9fe9. Report an issue: GitHub.