nexu-io/open-design · error
delete proposal requires targetRef
Error message
delete proposal requires targetRef
What it means
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).
Source
Thrown at apps/daemon/src/automation-proposals.ts:164
const lines = text.split(/\r?\n/);
const hasProposal = lines.some((line) => /^Proposal:\s*/i.test(line));
const existingPackets = new Set(
lines
.map((line) => /^Source packet:\s*([A-Za-z0-9_-]+)\s*$/i.exec(line)?.[1])
.filter((id): id is string => Boolean(id)),
);
const provenance: string[] = [];
for (const packetId of proposal.sourcePacketIds ?? []) {
if (!existingPackets.has(packetId)) provenance.push(`Source packet: ${packetId}`);
}
if (!hasProposal) provenance.push(`Proposal: ${proposal.id}`);
if (provenance.length === 0) return text;
return [text, '', ...provenance].join('\n');
}
async function applyMemoryProposal(dataDir: string, proposal: AutomationEvolutionProposal) {
if (proposal.action === 'delete') {
if (!proposal.targetRef) throw new Error('delete proposal requires targetRef');
await deleteMemoryEntry(dataDir, proposal.targetRef);
return { memoryId: proposal.targetRef, action: 'delete' };
}
const before = proposal.targetRef
? await readMemoryEntry(dataDir, proposal.targetRef)
: null;
const json = parseJsonPatchAfter(proposal);
const metadata =
proposal.metadata && typeof proposal.metadata === 'object' && !Array.isArray(proposal.metadata)
? proposal.metadata as Record<string, unknown>
: {};
const type = safeMemoryType(json.type ?? metadata.memoryType ?? before?.type);
const body =
typeof json.body === 'string'
? json.body
: typeof json.markdown === 'string'
? json.markdownView on GitHub (pinned to 5be4028344)
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).
Example fix
// before
{ targetKind: 'memory-node', action: 'delete', patch: { format: 'json', after: '{}' } }
// after
{ targetKind: 'memory-node', action: 'delete', targetRef: 'mem_abc123', patch: { format: 'json', after: '{}' } } Defensive patterns
Strategy: validation
Validate before calling
if (proposal.action === 'delete' && !proposal.targetRef) {
throw new Error('delete proposal requires targetRef');
} Type guard
function isDeletableMemoryProposal(p: { action: string; targetRef?: string }): boolean {
return p.action !== 'delete' || typeof p.targetRef === 'string' && p.targetRef.length > 0;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- proposal body is required
- proposal title is required
- proposal summary is required
- proposal patch is required
- proposal ${proposal.id} is ${proposal.status}, not reviewabl
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/15a8ca2a38dcfad9.
Report an issue: GitHub.