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

  1. Set sourceKind to exactly one of: upload, url, repo, connector, artifact, chat (lowercase).
  2. If unsure, pick 'upload' for user-attached files, 'url' for fetched links, 'connector' for integration-sourced content.
  3. 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

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


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