nexu-io/open-design · error
proposal title is required
Error message
proposal title is required
What it means
Thrown by createAutomationProposal() when input.title is not a string or is empty/whitespace-only. title is required because it becomes the proposal's display name and, for skill/design-system targets, the fallback slug.
Source
Thrown at apps/daemon/src/automation-proposals.ts:79
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()}`,
title: input.title.trim(),
summary: input.summary.trim(),View on GitHub (pinned to 5be4028344)
Solutions
- Provide a non-empty title string.
- Map any client-side 'name'/'label' field to title before calling.
- For agent-generated proposals, derive a title from the first line of the patch body if one is not explicit.
Example fix
// before
await createAutomationProposal(dataDir, { title: ' ', summary: 'S', patch: { format: 'json', after: '{}' } });
// after
await createAutomationProposal(dataDir, { title: 'Add pricing memory', summary: 'S', patch: { format: 'json', after: '{}' } }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof input.title !== 'string' || !input.title.trim()) {
throw new Error('proposal title is required');
} Type guard
function hasNonEmptyTitle(value: unknown): value is string {
return typeof value === 'string' && value.trim().length > 0;
} Prevention
- Map any client 'name'/'label' field to title before calling.
- Derive a title from the first line of patch.after when one is not explicit.
- Validate title.trim() client-side.
When it happens
Trigger: POST to the proposals endpoint (or a direct call) with title omitted, empty, whitespace-only, or a non-string. The guard fires before summary and patch checks.
Common situations: Client form missing the title field; agent-generated proposal that left the title blank; field named differently in the client (e.g. 'name') and never mapped to title.
Related errors
- proposal body 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/5a0550557ee2df41.
Report an issue: GitHub.