{"record":{"id":"694d97db1728b5e2","repo":"nexu-io/open-design","slug":"model-required","errorCode":null,"errorMessage":"model required","messagePattern":"model required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":371,"sourceCode":"    loop,\n    promptInfluence,\n    compositionDir,\n    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,","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L353-L389","documentation":"Thrown by the media dispatch entry point when `model` is missing or empty. A model id (catalog name or arbitrary fal.ai path like \"fal-ai/flux/dev\") is required to select the renderer. This check runs right after the surface validation.","triggerScenarios":"Omitting the model argument entirely; passing an empty string; passing model as undefined/null/whitespace; relying on a default that does not exist for the chosen surface.","commonSituations":"Agent forgets the model field; config template with a blank model placeholder; caller assumes a per-surface default but none is set; model field dropped during JSON serialization.","solutions":["Supply a non-empty model id from the media catalog (e.g. \"flux-pro\") or a fal.ai path (e.g. \"fal-ai/flux/dev\").","If unsure which models exist, query the media catalog/registry first.","Ensure the model field is serialized and not stripped by your client.","Validate the request payload before dispatch so model is always present."],"exampleFix":"// before\n{ surface: \"image\", prompt: \"a cat\" }\n// after\n{ surface: \"image\", model: \"fal-ai/flux/dev\", prompt: \"a cat\" }","handlingStrategy":"validation","validationCode":"if (typeof model !== 'string' || model.trim() === '') throw new Error('model required');","typeGuard":"function isNonEmptyModel(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Make model a required field in your tool schema.","Query the media catalog for valid model ids.","Serialize requests so the model field is never dropped."],"tags":["media","validation","required-field","model"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}