nexu-io/open-design · error
sourceKind must be one of upload, url, repo, connector, arti
Error message
sourceKind must be one of upload, url, repo, connector, artifact, chat
What it means
Thrown by sourceKindFrom() in ingestAutomationSource when input.sourceKind is not one of upload, url, repo, connector, artifact, chat. Unlike sensitivity/compression/reviewPolicy (which fall back silently), sourceKind is required and has no default, so an unknown value is a hard error.
Source
Thrown at apps/daemon/src/automation-ingestions.ts:107
): Promise<AutomationContentPacket | null> {
const packets = await listAutomationSourcePackets(dataDir);
return packets.find((packet) => packet.id === id) ?? null;
}
function asString(value: unknown): string {
return typeof value === 'string' ? value.trim() : '';
}
function optionalString(value: unknown): string | undefined {
const text = asString(value);
return text ? text : undefined;
}
function sourceKindFrom(value: unknown): AutomationSourceKind {
if (typeof value === 'string' && SOURCE_KINDS.has(value as AutomationSourceKind)) {
return value as AutomationSourceKind;
}
throw new Error('sourceKind must be one of upload, url, repo, connector, artifact, chat');
}
function sensitivityFrom(value: unknown): AutomationSensitivity {
if (typeof value === 'string' && SENSITIVITY_VALUES.has(value as AutomationSensitivity)) {
return value as AutomationSensitivity;
}
return 'workspace';
}
function compressionModeFrom(
value: unknown,
fallback: AutomationTokenCompressionMode,
): AutomationTokenCompressionMode {
if (typeof value === 'string' && COMPRESSION_MODES.has(value as AutomationTokenCompressionMode)) {
return value as AutomationTokenCompressionMode;
}
return fallback;
}View on GitHub (pinned to 5be4028344)
Solutions
- Set sourceKind to exactly one of: upload, url, repo, connector, artifact, chat (lowercase).
- If unsure, pick 'upload' for user-attached files, 'url' for fetched links, 'connector' for integration-sourced content.
- Update the client SDK/contract type to surface the allowed values at compile time.
Example fix
// before
fetch(url, { method: 'POST', body: JSON.stringify({ sourceKind: 'uploaded', bodyMarkdown: '...' }) })
// after
fetch(url, { method: 'POST', body: JSON.stringify({ sourceKind: 'upload', bodyMarkdown: '...' }) }) Defensive patterns
Strategy: type-guard
Validate before calling
const ALLOWED_SOURCE_KINDS = new Set(['upload','url','repo','connector','artifact','chat']);
if (!ALLOWED_SOURCE_KINDS.has(input.sourceKind)) {
throw new Error(`sourceKind must be one of ${[...ALLOWED_SOURCE_KINDS].join(', ')}`);
} Type guard
const SOURCE_KINDS = new Set(['upload','url','repo','connector','artifact','chat']);
function isAutomationSourceKind(v: unknown): v is 'upload'|'url'|'repo'|'connector'|'artifact'|'chat' {
return typeof v === 'string' && SOURCE_KINDS.has(v as any);
} Prevention
- Use the AutomationSourceKind contract type from @open-design/contracts so the compiler catches typos.
- Send lowercase canonical values; the check is case-sensitive.
- Validate sourceKind on the client before posting.
When it happens
Trigger: POST to the ingestion endpoint with sourceKind missing, misspelled (e.g. 'uploaded', 'repository', 'Github'), or using a wrong-case variant ('Upload'). The check is case-sensitive against the literal set.
Common situations: Client SDK typo; integration sending a connector-specific verb instead of the canonical 'connector'; case mismatch; an older client using a value that was renamed.
Related errors
- ingestion body is required
- bodyMarkdown is required
- proposal body is required
- proposal title is required
- proposal summary is required
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/e69695c20dda691d.
Report an issue: GitHub.