nexu-io/open-design · error
proposal patch is required
Error message
proposal patch is required
What it means
Thrown by createAutomationProposal() when input.patch is falsy or not an object. patch carries the proposed change (format + after + diffSummary) and is the load-bearing field — a proposal without a patch has nothing to apply.
Source
Thrown at apps/daemon/src/automation-proposals.ts:85
}
export async function createAutomationProposal(
dataDir: string,
input: CreateAutomationEvolutionProposalRequest & {
id?: string;
status?: AutomationProposalStatus;
},
): Promise<AutomationEvolutionProposal> {
const now = new Date().toISOString();
if (!input || typeof input !== 'object') throw new Error('proposal body is required');
if (typeof input.title !== 'string' || !input.title.trim()) {
throw new Error('proposal title is required');
}
if (typeof input.summary !== 'string' || !input.summary.trim()) {
throw new Error('proposal summary is required');
}
if (!input.patch || typeof input.patch !== 'object') {
throw new Error('proposal patch is required');
}
const status =
input.status && VALID_STATUSES.has(input.status)
? input.status
: 'pending-review';
const proposal: AutomationEvolutionProposal = {
id:
typeof input.id === 'string' && input.id.trim()
? input.id.trim()
: `proposal_${randomUUID()}`,
title: input.title.trim(),
summary: input.summary.trim(),
targetKind: input.targetKind,
action: input.action,
status,
reviewPolicy: input.reviewPolicy ?? 'always',
createdAt: now,
updatedAt: now,View on GitHub (pinned to 5be4028344)
Solutions
- Supply patch as an object with at least format ('json' or 'markdown'), after (string), and diffSummary.
- If patch was serialized to a string, JSON.parse it before calling.
- Mirror the patch shape produced by buildMemoryProposalPatch / buildDesignSystemProposalMarkdown in automation-ingestions.ts.
Example fix
// before
await createAutomationProposal(dataDir, { title: 'T', summary: 'S', patch: '{"format":"json"}' });
// after
await createAutomationProposal(dataDir, {
title: 'T', summary: 'S',
patch: { format: 'json', after: '{"body":"..."}', diffSummary: 'create entry' }
}); Defensive patterns
Strategy: type-guard
Validate before calling
if (!input.patch || typeof input.patch !== 'object') {
throw new Error('proposal patch is required');
} Type guard
function isPatchObject(value: unknown): value is { format?: string; after?: string; diffSummary?: string } {
return !!value && typeof value === 'object' && !Array.isArray(value);
} Prevention
- Nest diffSummary under patch, not at the top level.
- Use JSON.stringify for json-format patches rather than template literals.
- Mirror the patch shapes from automation-ingestions.ts.
When it happens
Trigger: POST to the proposals endpoint with patch omitted, null, an array, a string, or any non-object. Fires after title and summary checks pass.
Common situations: Client sending diffSummary as the top-level field instead of nesting it under patch; caller passing a JSON string for patch instead of an object; agent emitting a proposal before serializing its patch.
Related errors
- proposal body is required
- proposal title is required
- proposal summary is required
- sourceKind must be one of upload, url, repo, connector, arti
- ingestion body is required
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/178717c4807769a5.
Report an issue: GitHub.