{"record":{"id":"85dfd7b1bdbee696","repo":"langgenius/dify","slug":"invalid-type-req-data-type","errorCode":null,"errorMessage":"Invalid type: {req_data.type}","messagePattern":"Invalid type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"api/controllers/console/app/generator.py","lineNumber":446,"sourceCode":"    @console_ns.expect(console_ns.models[InstructionTemplatePayload.__name__])\n    @console_ns.response(200, \"Template retrieved successfully\", console_ns.models[SimpleDataResponse.__name__])\n    @console_ns.response(400, \"Invalid request parameters\")\n    @setup_required\n    @login_required\n    @account_initialization_required\n    @model_validate(InstructionTemplatePayload)\n    def post(self, req_data: InstructionTemplatePayload):\n        match req_data.type:\n            case \"prompt\":\n                from core.llm_generator.prompts import INSTRUCTION_GENERATE_TEMPLATE_PROMPT\n\n                return {\"data\": INSTRUCTION_GENERATE_TEMPLATE_PROMPT}\n            case \"code\":\n                from core.llm_generator.prompts import INSTRUCTION_GENERATE_TEMPLATE_CODE\n\n                return {\"data\": INSTRUCTION_GENERATE_TEMPLATE_CODE}\n            case _:\n                raise ValueError(f\"Invalid type: {req_data.type}\")\n\n\ndef _workflow_instruction_guard(args: WorkflowGeneratePayload) -> tuple[dict, int] | None:\n    \"\"\"Shared boundary guard for the workflow-generate endpoints.\n\n    Returns a ``(body, 400)`` tuple when the instruction is empty / whitespace\n    or either free-text field exceeds the cap, else ``None``. Pydantic only\n    validates the field is a str; a whitespace-only or pasted-document input\n    would otherwise waste a slow planner+builder roundtrip on a response the\n    validator rejects anyway. Both the blocking and streaming endpoints call\n    this so they reject identical inputs.\n    \"\"\"\n    if not args.instruction.strip():\n        return {\n            \"error\": \"Instruction is required\",\n            \"errors\": [{\"code\": WorkflowGenerateErrorCode.EMPTY_INSTRUCTION, \"detail\": \"Instruction is required\"}],\n        }, 400\n    if len(args.instruction) > _MAX_INSTRUCTION_LENGTH or len(args.ideal_output) > _MAX_INSTRUCTION_LENGTH:","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/generator.py#L428-L464","documentation":"ValueError raised by InstructionGenerationTemplateApi.post when req_data.type does not match 'prompt' or 'code' in the match/case. Only those two template types are defined. Flask maps the uncaught ValueError to a 400 response with the message including the offending value.","triggerScenarios":"POST /console/api/apps/<app_id>/instruction-generate/template with a body whose 'type' field is anything other than 'prompt' or 'code' (e.g. 'text', 'json', empty, or a typo like 'promt').","commonSituations":"Client sending a wrong type string; frontend regression that stopped constraining the dropdown; API consumer guessing the field vocabulary.","solutions":["Send type='prompt' or type='code' in the request body.","If you need a new template type, extend the match/case in generator.py and add the template constant in core/llm_generator/prompts.py.","Add a client-side enum/dropdown limited to the two valid values to prevent invalid submissions."],"exampleFix":"// before\nPOST /instruction-generate/template  { \"type\": \"text\" }\n// after\nPOST /instruction-generate/template  { \"type\": \"prompt\" }","handlingStrategy":"type-guard","validationCode":"const VALID_TEMPLATE_TYPES = new Set(['prompt', 'code']);\nfunction isValidTemplateType(t: string): boolean {\n  return VALID_TEMPLATE_TYPES.has(t);\n}\n// guard before send\nif (!isValidTemplateType(payload.type)) throw new Error(`type must be prompt or code, got ${payload.type}`);","typeGuard":"type InstructionTemplateType = 'prompt' | 'code';\nfunction isInstructionTemplateType(t: string): t is InstructionTemplateType {\n  return t === 'prompt' || t === 'code';\n}","tryCatchPattern":null,"preventionTips":["Drive the type field from a constrained dropdown, never free text.","Validate client-side against the literal union before posting.","If extending the vocabulary, update both client and server match/case in lockstep."],"tags":["validation","enum","template","instruction-generate","match-case"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}