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

  1. Pass a parsed object containing at least title, summary, and patch.
  2. Ensure the HTTP layer applies JSON body parsing before reaching the service.
  3. 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

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


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/a79f8806de7ccd45. Report an issue: GitHub.