{"record":{"id":"23aabf4a2f806576","repo":"nexu-io/open-design","slug":"unsupported-audiokind-audiokind-allowed-musi","errorCode":null,"errorMessage":"unsupported audioKind: ${audioKind}. Allowed: music | speech | sfx.","messagePattern":"unsupported audioKind: (.+?)\\. Allowed: music \\| speech \\| sfx\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":374,"sourceCode":"    image,\n    requestInit,\n    workspaceId,\n    onProviderRequestSettled,\n  } = args;\n\n  if (!projectRoot) throw new Error('projectRoot required');\n  if (!projectsRoot) throw new Error('projectsRoot required');\n  if (typeof projectId !== 'string' || !projectId) {\n    throw new Error('projectId required');\n  }\n  if (!SURFACES.has(surface)) {\n    throw new Error(`unsupported surface: ${surface}`);\n  }\n  if (typeof model !== 'string' || !model) {\n    throw new Error('model required');\n  }\n  if (surface === 'audio' && audioKind && !AUDIO_KINDS.has(audioKind)) {\n    throw new Error(\n      `unsupported audioKind: ${audioKind}. Allowed: music | speech | sfx.`,\n    );\n  }\n  // Arbitrary fal.ai model paths (e.g. \"fal-ai/flux/dev\") bypass the\n  // catalog so users can reach any model on fal without waiting for a\n  // catalog entry. Surface comes from the caller; no cross-surface guard\n  // is needed because the fal renderer reads ctx.surface directly.\n  let def = findMediaModel(model);\n  let isFalCustomPath = false;\n  let isCatalogBypass = false;\n  if (!def) {\n    if (/^fal-ai\\//.test(model)) {\n      isFalCustomPath = true;\n      def = {\n        id: model,\n        label: model,\n        hint: 'Fal.ai',\n        provider: 'fal',","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L356-L392","documentation":"Thrown by the media dispatcher's input-validation block when surface is 'audio' and a non-empty audioKind is supplied that is not one of the three allowed kinds. The set AUDIO_KINDS = {'music','speech','sfx'} is the only accepted vocabulary. The check runs before model resolution, so no provider is contacted.","triggerScenarios":"Calling od media generate (or POST /api/media/generate) with --surface audio and an --audio-kind value other than music/speech/sfx (e.g. 'voice', 'instrumental', 'sound', or a typo like 'musci'). An agent hallucinating an audio-kind argument also lands here.","commonSituations":"Agent-generated CLI invocations inventing vocabulary; UI dropdown out of sync with the backend enum; user assuming 'voice' is valid because speech TTS uses voices; copy/paste from older docs that listed different kinds.","solutions":["Re-run with --audio-kind set to one of music, speech, or sfx (omit the flag entirely to default to music).","If invoking programmatically, source the allowed set from the catalog (e.g. GET /api/media/models filtered by surface=audio) rather than hard-coding.","Update the calling agent's prompt or tool schema so the audioKind enum matches the backend exactly."],"exampleFix":"// before\nod media generate --surface audio --model gpt-4o-mini-tts --audio-kind voice --prompt \"hi\"\n// after\nod media generate --surface audio --model gpt-4o-mini-tts --audio-kind speech --prompt \"hi\"","handlingStrategy":"validation","validationCode":"const AUDIO_KINDS = new Set(['music', 'speech', 'sfx']);\nfunction validateAudioKind(kind: string | undefined): string | undefined {\n  if (kind === undefined || kind === '') return undefined;\n  if (!AUDIO_KINDS.has(kind)) {\n    throw new Error(`unsupported audioKind: ${kind}. Allowed: music | speech | sfx.`);\n  }\n  return kind;\n}\n// call before od media generate:\nconst safeKind = validateAudioKind(args.audioKind);","typeGuard":"function isAudioKind(v: unknown): v is 'music' | 'speech' | 'sfx' {\n  return typeof v === 'string' && ['music', 'speech', 'sfx'].includes(v);\n}","tryCatchPattern":null,"preventionTips":["Source the allowed audioKind enum from /api/media/models rather than hard-coding it in the caller.","Constrain the agent tool schema for audioKind to enum: [music, speech, sfx].","Default to omitting --audio-kind (the dispatcher defaults to music) rather than guessing."],"tags":["validation","media","audio","argument-validation"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}