{"record":{"id":"15a8ca2a38dcfad9","repo":"nexu-io/open-design","slug":"delete-proposal-requires-targetref","errorCode":null,"errorMessage":"delete proposal requires targetRef","messagePattern":"delete proposal requires targetRef","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/daemon/src/automation-proposals.ts","lineNumber":164,"sourceCode":"  const lines = text.split(/\\r?\\n/);\n  const hasProposal = lines.some((line) => /^Proposal:\\s*/i.test(line));\n  const existingPackets = new Set(\n    lines\n      .map((line) => /^Source packet:\\s*([A-Za-z0-9_-]+)\\s*$/i.exec(line)?.[1])\n      .filter((id): id is string => Boolean(id)),\n  );\n  const provenance: string[] = [];\n  for (const packetId of proposal.sourcePacketIds ?? []) {\n    if (!existingPackets.has(packetId)) provenance.push(`Source packet: ${packetId}`);\n  }\n  if (!hasProposal) provenance.push(`Proposal: ${proposal.id}`);\n  if (provenance.length === 0) return text;\n  return [text, '', ...provenance].join('\\n');\n}\n\nasync function applyMemoryProposal(dataDir: string, proposal: AutomationEvolutionProposal) {\n  if (proposal.action === 'delete') {\n    if (!proposal.targetRef) throw new Error('delete proposal requires targetRef');\n    await deleteMemoryEntry(dataDir, proposal.targetRef);\n    return { memoryId: proposal.targetRef, action: 'delete' };\n  }\n\n  const before = proposal.targetRef\n    ? await readMemoryEntry(dataDir, proposal.targetRef)\n    : null;\n  const json = parseJsonPatchAfter(proposal);\n  const metadata =\n    proposal.metadata && typeof proposal.metadata === 'object' && !Array.isArray(proposal.metadata)\n      ? proposal.metadata as Record<string, unknown>\n      : {};\n  const type = safeMemoryType(json.type ?? metadata.memoryType ?? before?.type);\n  const body =\n    typeof json.body === 'string'\n      ? json.body\n      : typeof json.markdown === 'string'\n        ? json.markdown","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/automation-proposals.ts#L146-L182","documentation":"Thrown by applyMemoryProposal() when proposal.action === 'delete' but proposal.targetRef is missing. A delete needs to know which memory entry to remove; without targetRef there is nothing to delete. Non-delete actions do not require targetRef (they can create a new entry).","triggerScenarios":"Applying a memory-node proposal with action 'delete' that was created without a targetRef. The create-time validation does not enforce targetRef for memory deletes, so the error surfaces only at apply time.","commonSituations":"Agent emitted a delete proposal pointing at a target by name/id in metadata instead of targetRef; proposal was hand-crafted; ingestion pipeline built a delete from a stale reference that was never populated.","solutions":["Update the proposal record to include targetRef pointing at the memory entry id/path to delete.","If the target no longer exists, mark the proposal 'rejected' instead of applying it.","When building memory-delete proposals, always set targetRef (and validate it before persisting)."],"exampleFix":"// before\n{ targetKind: 'memory-node', action: 'delete', patch: { format: 'json', after: '{}' } }\n// after\n{ targetKind: 'memory-node', action: 'delete', targetRef: 'mem_abc123', patch: { format: 'json', after: '{}' } }","handlingStrategy":"validation","validationCode":"if (proposal.action === 'delete' && !proposal.targetRef) {\n  throw new Error('delete proposal requires targetRef');\n}","typeGuard":"function isDeletableMemoryProposal(p: { action: string; targetRef?: string }): boolean {\n  return p.action !== 'delete' || typeof p.targetRef === 'string' && p.targetRef.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always set targetRef on memory-node delete proposals at create time.","Validate targetRef presence before persisting a delete proposal.","Reject delete proposals whose target no longer exists instead of applying."],"tags":["automation","proposals","memory","validation","daemon"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}