{"record":{"id":"520ada0320ff5b82","repo":"HeyPuter/puter","slug":"bad-request-520ada","errorCode":"bad_request","errorMessage":"`prompt` must be a non-empty string","messagePattern":"`prompt` must be a non-empty string","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/drivers/ai-image/providers/cloudflare/CloudflareImageProvider.ts","lineNumber":97,"sourceCode":"        return CLOUDFLARE_IMAGE_GENERATION_MODELS;\n    }\n\n    getDefaultModel(): string {\n        return DEFAULT_MODEL;\n    }\n\n    async generate(params: IGenerateParams): Promise<string> {\n        const options = params as CloudflareGenerateParams;\n        const { prompt, test_mode } = options;\n        const ratio = this.#normalizeRatio(options.ratio);\n        const selectedModel = this.#getModel(options.model);\n\n        if (test_mode) {\n            return 'https://puter-sample-data.puter.site/image_example.png';\n        }\n\n        if (typeof prompt !== 'string' || prompt.trim().length === 0) {\n            throw new HttpError(400, '`prompt` must be a non-empty string', {\n                legacyCode: 'bad_request',\n            });\n        }\n\n        const actor = Context.get('actor');\n        if (!actor) {\n            throw new HttpError(401, 'actor not found in context', {\n                legacyCode: 'unauthorized',\n            });\n        }\n\n        // Canonical `input_images`/`input_image` → Cloudflare's `image` field.\n        // Cloudflare accepts a single input image; a URL is fetched to base64\n        // server-side (SSRF-guarded) since the API has no URL field.\n        const singleInput = resolveSingleInputImage(options, 'Cloudflare');\n        if (singleInput) {\n            options.image ??= isHttpUrl(singleInput)\n                ? (await fetchImageAsBase64(singleInput)).base64","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-image/providers/cloudflare/CloudflareImageProvider.ts#L79-L115","documentation":"CloudflareImageProvider.generate requires a prompt that is a string and non-empty after trim; anything else (undefined, number, empty, whitespace-only) throws HTTP 400 bad_request before doing any work or spending credits.","triggerScenarios":"Calling Cloudflare image generation with no prompt, an empty prompt, or a non-string prompt (e.g. passing an object or number by mistake).","commonSituations":"UI submitting before the user typed a prompt; variable not initialized; prompt built from an empty template field.","solutions":["Ensure prompt is a non-empty trimmed string before calling generate().","Disable the submit UI until a prompt is entered.","Type-check/guard prompt at the call site."],"exampleFix":"// before\nawait provider.generate({ prompt: '' });\n// after\nif (typeof prompt !== 'string' || prompt.trim().length === 0) throw new Error('prompt required');\nawait provider.generate({ prompt });","handlingStrategy":"validation","validationCode":"if (typeof prompt !== 'string' || prompt.trim().length === 0) {\n  throw new Error('prompt must be a non-empty string');\n}","typeGuard":"function isNonEmptyPrompt(p) {\n  return typeof p === 'string' && p.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Disable the submit action until a non-empty prompt is entered.","Type-check prompt at the call site.","Strip and validate before passing to generate()."],"tags":["ai-image","cloudflare","validation","prompt","bad-request"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}