{"record":{"id":"acd831ca3eb5990b","repo":"abi/screenshot-to-code","slug":"unsupported-input-mode-input-mode","errorCode":null,"errorMessage":"Unsupported input mode: {input_mode}","messagePattern":"Unsupported input mode: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/prompts/create/__init__.py","lineNumber":45,"sourceCode":"        return build_text_prompt_messages(\n            text_prompt=prompt[\"text\"],\n            stack=stack,\n            image_generation_enabled=image_generation_enabled,\n            design_system=design_system,\n        )\n    if input_mode == \"video\":\n        video_urls = prompt.get(\"videos\", [])\n        if not video_urls:\n            raise ValueError(\"Video mode requires a video to be provided\")\n        video_url = video_urls[0]\n        return build_video_prompt_messages(\n            video_data_url=video_url,\n            stack=stack,\n            text_prompt=prompt.get(\"text\", \"\"),\n            image_generation_enabled=image_generation_enabled,\n            design_system=design_system,\n        )\n    raise ValueError(f\"Unsupported input mode: {input_mode}\")\n\n\n__all__ = [\"build_create_prompt_from_input\"]\n","sourceCodeStart":27,"sourceCodeEnd":49,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/prompts/create/__init__.py#L27-L49","documentation":"Raised at the bottom of build_create_prompt_from_input when input_mode is none of \"image\", \"text\", or \"video\" — the only three branches the builder implements. The Literal InputMode type promises one of those values, so hitting this means an untyped/improperly validated value reached a typed boundary (the value is echoed in the message).","triggerScenarios":"Calling the builder with input_mode=\"audio\", \"\", None, or a differently-cased \"Image\". In the live app: the WebSocket route passing raw JSON inputMode from the client straight through without narrowing, or a new mode added to the frontend before backend support.","commonSituations":"Frontend/backend version skew after adding a new input mode; hand-rolled API clients sending arbitrary strings; typo or casing mismatch in the payload field.","solutions":["Send one of the supported values exactly: \"image\", \"text\", or \"video\".","Validate and reject unknown inputMode at the route boundary (return 400) before it reaches the builder.","If adding a new mode, implement its branch in build_create_prompt_from_input and widen the InputMode Literal in the same change.","Check frontend/backend versions are in sync when a new mode is involved."],"exampleFix":"# before\nbuild_create_prompt_from_input(prompt, input_mode=\"audio\", stack=stack)\n\n# after — supported mode\nbuild_create_prompt_from_input(prompt, input_mode=\"video\", stack=stack)","handlingStrategy":"validation","validationCode":"SUPPORTED_INPUT_MODES = {\"image\", \"text\", \"video\"}\n\ndef is_supported_input_mode(mode: str) -> bool:\n    return mode in SUPPORTED_INPUT_MODES","typeGuard":"from typing import Literal\n\nInputModeT = Literal[\"image\", \"video\", \"text\"]\n\ndef is_input_mode(value: object) -> TypeGuard[InputModeT]:\n    return isinstance(value, str) and value in (\"image\", \"video\", \"text\")","tryCatchPattern":"try:\n    messages = build_create_prompt_from_input(prompt, input_mode, stack)\nexcept ValueError as e:\n    if str(e).startswith(\"Unsupported input mode\"):\n        return error_response(f\"inputMode must be image|text|video, got {input_mode!r}\", 400)\n    raise","preventionTips":["Validate inputMode against the Literal at the API boundary and 400 on unknowns","Add the backend branch in the same commit that widens the InputMode Literal","Pin frontend and backend versions together when introducing new modes"],"tags":["prompts","validation","input-mode","api-contract"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}