HeyPuter/puter · error · HttpError
bad_request
bad_request
Error message
`prompt` must be a non-empty string
What it means
Thrown by GeminiImageProvider.generate() (GeminiImageProvider.ts:88) before any upstream API call when the `prompt` field is not a string or contains only whitespace. It is a hard precondition: the Gemini generateContent path needs a text prompt to embed as the first content part, so an empty/missing prompt cannot produce a meaningful request. The check runs after test_mode short-circuit, so test calls never hit it.
Source
Thrown at src/backend/drivers/ai-image/providers/gemini/GeminiImageProvider.ts:89
async generate(params: IGenerateParams): Promise<string> {
const { prompt, test_mode, input_image, input_image_mime_type, model } =
params;
let { ratio, input_images, quality } = params;
const selectedModel =
(this.models() as IGeminiImageModel[]).find(
(m) => m.id === model,
) ||
(this.models() as IGeminiImageModel[]).find(
(m) => m.id === this.getDefaultModel(),
)!;
if (test_mode) {
return 'https://puter-sample-data.puter.site/image_example.png';
}
if (typeof prompt !== 'string' || prompt.trim().length === 0) {
throw new HttpError(400, '`prompt` must be a non-empty string', {
legacyCode: 'bad_request',
});
}
if (selectedModel.apiType === 'generateImages') {
return this.#generateWithImagen(prompt, selectedModel, params);
}
const allowedRatios = selectedModel.allowedRatios ?? [
GEMINI_DEFAULT_RATIO,
];
ratio =
ratio && this.#isValidRatio(ratio, allowedRatios)
? ratio
: allowedRatios[0];
// Backwards compat: merge singular input_image into input_images
if (input_image && (!input_images || input_images.length === 0)) {View on GitHub (pinned to 908ec23eda)
Solutions
- Ensure the caller passes a non-empty string as `prompt` before invoking generate().
- Validate at the controller/driver boundary: reject requests where prompt is missing or blank, returning bad_request before reaching the provider.
- If building prompts dynamically, guard with `if (!prompt?.trim()) return;` or fall back to a default description.
Example fix
// before
await provider.generate({ prompt: userPrompt });
// after
if (typeof userPrompt !== 'string' || userPrompt.trim().length === 0) {
throw new HttpError(400, 'prompt is required', { legacyCode: 'bad_request' });
}
await provider.generate({ prompt: userPrompt }); Defensive patterns
Strategy: validation
Validate before calling
function assertNonEmptyPrompt(prompt: unknown): asserts prompt is string {
if (typeof prompt !== 'string' || prompt.trim().length === 0) {
throw new Error('`prompt` must be a non-empty string');
}
}
// before calling generate():
assertNonEmptyPrompt(params.prompt); Type guard
function isValidPrompt(prompt: unknown): prompt is string {
return typeof prompt === 'string' && prompt.trim().length > 0;
} Try / catch
try {
await provider.generate(params);
} catch (e) {
if (e instanceof HttpError && e.status_code === 400 && e.message.includes('prompt')) {
// surface a user-friendly validation error
}
throw e;
} Prevention
- Validate prompt at the API/controller boundary before forwarding to any provider.
- Treat prompt as required in your request schema (e.g. zod, JSON schema).
- Default to rejecting empty/whitespace input explicitly rather than relying on the provider.
When it happens
Trigger: Calling provider.generate({}) with no prompt; passing prompt: '' or prompt: ' '; passing prompt: null or prompt: 123; passing prompt: undefined. Any non-string or whitespace-only value reaches line 88 and throws.
Common situations: A controller or driver layer forwards user input without validating `prompt`; a caller passes a form field that was left blank; JSON deserialization yields null where a string was expected; programmatic callers defaulting prompt to an empty string.
Related errors
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/57ffa0e19f43e36b.
Report an issue: GitHub.