{"record":{"id":"7814f38cb282dc29","repo":"musistudio/claude-code-router","slug":"prompt-is-required","errorCode":null,"errorMessage":"prompt is required.","messagePattern":"prompt is required\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/media/service.ts","lineNumber":591,"sourceCode":"    if (!this.running || !config.mediaTools.enabled) throw new Error(\"Media service is disabled.\");\n    return config.mediaTools;\n  }\n\n  private executor(modelSelector: string, operation?: MediaOperation): GatewayMediaExecutor {\n    const transport = this.gatewayTransport;\n    if (!transport) throw new Error(\"Media gateway transport is not configured.\");\n    return new GatewayMediaExecutor(resolveProviderMediaTarget(this.requireConfig(), modelSelector, operation), transport);\n  }\n}\n\nfunction createCompletion(): Completion {\n  let resolve!: (job: MediaJob) => void;\n  const promise = new Promise<MediaJob>((value) => { resolve = value; });\n  return { promise, resolve };\n}\n\nfunction requiredPrompt(value: unknown): string {\n  if (typeof value !== \"string\" || !value.trim()) throw new Error(\"prompt is required.\");\n  const prompt = value.trim();\n  return prompt;\n}\n\nfunction optionalString(value: unknown): string | undefined {\n  return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n  return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction mediaModelAttempts(plan: MediaModelPlan): string[] {\n  const attempts: string[] = [];\n  for (const modelSelector of [plan.modelSelector, ...plan.fallbackModelSelectors]) {\n    for (let index = 0; index <= plan.retryCount; index += 1) {\n      attempts.push(modelSelector);\n    }","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/media/service.ts#L573-L609","documentation":"requiredPrompt coerces the tool's prompt argument: it must be a string with non-whitespace content after trimming. Missing, non-string, or blank prompts fail before any model call.","triggerScenarios":"Calling a media generation tool with prompt: undefined, a number/object, or \"   \".","commonSituations":"MCP client forwards unvalidated JSON arguments; prompt field name mismatch (e.g. text vs prompt); empty template string interpolation.","solutions":["Always pass a non-empty trimmed string as prompt","Validate tool arguments against the tool's input schema before invoking","Guard against empty interpolation from variables"],"exampleFix":"// before\n{ prompt: ``, images: [...] }\n// after\n{ prompt: \"Edit: remove the background\", images: [...] }","handlingStrategy":"type-guard","validationCode":"if (typeof args.prompt !== \"string\" || !args.prompt.trim()) throw new TypeError(\"prompt required\");","typeGuard":"const hasPrompt = (a: { prompt?: unknown }): a is { prompt: string } => typeof a.prompt === \"string\" && a.prompt.trim().length > 0;","tryCatchPattern":"try { await tool(args); } catch (e) { if (e instanceof Error && e.message === \"prompt is required.\") return badRequest(); throw e; }","preventionTips":["Schema-validate MCP tool arguments","Default prompts to undefined, not empty string"],"tags":["media","validation","prompt"],"backgroundTag":"required-argument-missing","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}