{"record":{"id":"1266826417872301","repo":"affaan-m/ECC","slug":"missing-work-item-id-pass-id-or-id-id","errorCode":null,"errorMessage":"Missing work item id. Pass <id> or --id <id>.","messagePattern":"Missing work item id\\. Pass <id> or --id <id>\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/work-items.js","lineNumber":320,"sourceCode":"    );\n  }\n\n  const closedItems = closeStaleGithubItems(store, repo, activeIds, { limit: Math.max(limit * 4, 1000) });\n  return {\n    repo,\n    syncedAt,\n    prCount: prs.length,\n    issueCount: issues.length,\n    closedCount: closedItems.length,\n    items,\n    closedItems\n  };\n}\n\nfunction buildUpsertPayload(options, existing = null) {\n  const id = resolveWorkItemId(options);\n  if (!id) {\n    throw new Error('Missing work item id. Pass <id> or --id <id>.');\n  }\n\n  const title = options.title ?? (existing && existing.title);\n  if (!title) {\n    throw new Error('Missing --title for a new work item.');\n  }\n\n  return {\n    id,\n    source: options.source ?? (existing && existing.source) ?? 'manual',\n    sourceId: options.sourceId ?? (existing && existing.sourceId) ?? null,\n    title,\n    status: options.status ?? (existing && existing.status) ?? 'open',\n    priority: options.priority ?? (existing && existing.priority) ?? null,\n    url: options.url ?? (existing && existing.url) ?? null,\n    owner: options.owner ?? (existing && existing.owner) ?? null,\n    repoRoot: options.repoRoot ?? (existing && existing.repoRoot) ?? process.cwd(),\n    sessionId: options.sessionId ?? (existing && existing.sessionId) ?? null,","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/work-items.js#L302-L338","documentation":"Thrown by buildUpsertPayload() when resolveWorkItemId(options) returns null, i.e. neither options.id nor options.positionals[0] is set (resolveWorkItemId at line 133-135). Every upsert needs a stable local id because the SQLite store keys work items on it; upsert with no id cannot decide between insert and update.","triggerScenarios":"Calling the 'upsert' command with no positional id and no --id flag, e.g. `node scripts/work-items.js upsert --title \"x\"`. Also triggered when calling buildUpsertPayload() directly without setting options.id or options.positionals. The 'close' command does its own id check first (error 487) so it does not reach this path.","commonSituations":"Assuming the title or source-id is enough to identify the item; forgetting that upsert requires an explicit local id (it is not auto-generated); migrating a script that previously used only --source-id.","solutions":["Supply an id positionally: `node scripts/work-items.js upsert my-item --title \"My item\"`.","Or use --id: `node scripts/work-items.js upsert --id my-item --title \"My item\"`.","If importing from a source system, derive a stable id like `github-<owner-name-repo>-pr-<n>` so re-runs update rather than duplicate."],"exampleFix":"// before\nnode scripts/work-items.js upsert --title \"Refactor state store\"\n\n// after\nnode scripts/work-items.js upsert refactor-state-store --title \"Refactor state store\"","handlingStrategy":"validation","validationCode":"function ensureUpsertId(options) {\n  const id = options.id || (options.positionals && options.positionals[0]);\n  if (!id) throw new Error('upsert needs <id> or --id <id>');\n  options.id = id;\n  return options;\n}\n// call before buildUpsertPayload(ensureUpsertId(options), existing)","typeGuard":"function hasWorkItemId(options) {\n  return Boolean(options && (options.id || (options.positionals && options.positionals[0])));\n}","tryCatchPattern":null,"preventionTips":["Always pass an explicit, stable local id on upsert (derive one from the source system).","In scripts, resolve and set options.id before calling buildUpsertPayload.","Use a deterministic id scheme so re-runs update rather than duplicate."],"tags":["cli","validation","missing-argument","upsert","identifier"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}