nexu-io/open-design · error
proposal body is required
Error message
proposal body is required
What it means
Thrown by createAutomationProposal() as the first guard when the input argument is falsy or not an object. It is the top-level body-presence check that runs before field validation (title, summary, patch).
Source
Thrown at apps/daemon/src/automation-proposals.ts:77
}
export async function getAutomationProposal(
dataDir: string,
id: string,
): Promise<AutomationEvolutionProposal | null> {
const proposals = await listAutomationProposals(dataDir, { status: 'all' });
return proposals.find((proposal) => proposal.id === id) ?? null;
}
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()}`,View on GitHub (pinned to 5be4028344)
Solutions
- Pass a parsed object containing at least title, summary, and patch.
- Ensure the HTTP layer applies JSON body parsing before reaching the service.
- If constructing the input conditionally, default to an early return when fields are missing.
Example fix
// before
await createAutomationProposal(dataDir, null);
// after
await createAutomationProposal(dataDir, { title: 'T', summary: 'S', targetKind: 'memory-node', action: 'create', patch: { format: 'json', after: '{}' } }); Defensive patterns
Strategy: type-guard
Validate before calling
if (!input || typeof input !== 'object') {
throw new Error('proposal body is required');
} Type guard
function isProposalInput(value: unknown): value is Record<string, unknown> {
return !!value && typeof value === 'object' && !Array.isArray(value);
} Prevention
- Parse the request body as JSON before reaching the service.
- Construct the input as an object literal, not a serialized string.
- Guard conditionally-built inputs before calling.
When it happens
Trigger: Calling createAutomationProposal() directly or via POST to the proposals endpoint with null, undefined, a primitive, or an unparsed JSON string.
Common situations: Route handler missing body-parsing middleware; programmatic caller passing a serialized string; chained caller that conditionally built the body and ended up undefined.
Related errors
- proposal title is required
- proposal summary is required
- proposal patch 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/a79f8806de7ccd45.
Report an issue: GitHub.