{"record":{"id":"26c47a472c82baf9","repo":"zylon-ai/private-gpt","slug":"invalid-request-audio-max-num-error","errorCode":"INVALID_REQUEST_AUDIO_MAX_NUM_ERROR","errorMessage":"The LLM supports a maximum of {max_num_audios} audios, but the message contains {len(audios)}","messagePattern":"The LLM supports a maximum of (.+?) audios, but the message contains (.+?)","errorType":"http","errorClass":"Errors.InvalidRequest","httpStatus":400,"severity":"error","filePath":"private_gpt/server/chat/interceptors/validator_request_interceptor.py","lineNumber":104,"sourceCode":"            if len(images) > max_num_images:\n                raise Errors.InvalidRequest(\n                    f\"The LLM supports a maximum of {max_num_images} images, but the message contains {len(images)}\",\n                    Errors.Codes.INVALID_REQUEST_IMAGE_MAX_NUM_ERROR,\n                )\n\n        # Validate multimodal inputs (audios)\n        audios: list[AudioBlock] = [\n            audio for audio in last_user_message.blocks if isinstance(audio, AudioBlock)\n        ]\n        if audios:\n            if not supports_audio(llm, model_config):\n                raise Errors.InvalidRequest(\n                    \"The LLM does not support audio, but the message contains audio blocks.\",\n                    Errors.Codes.INVALID_REQUEST_AUDIO_SUPPORT_ERROR,\n                )\n            max_num_audios = max_audios_supported(llm, model_config)\n            if len(audios) > max_num_audios:\n                raise Errors.InvalidRequest(\n                    f\"The LLM supports a maximum of {max_num_audios} audios, but the message contains {len(audios)}\",\n                    Errors.Codes.INVALID_REQUEST_AUDIO_MAX_NUM_ERROR,\n                )\n\n        token_limit = context.state.runtime.effective_token_limit\n        tokenize = context.state.runtime.tokenizer_fn\n        if token_limit is None or tokenize is None:\n            return\n\n        user_message_tokens = len(\n            await async_tokenizer(texts=user_text, tokenizer_fn=tokenize)\n        )\n        if user_message_tokens > token_limit:\n            raise Errors.RequestTooLarge(\n                f\"The message length {user_message_tokens} exceeds the maximum token limit {token_limit}.\",\n                Errors.Codes.REQUEST_TOO_LARGE_USER_MSG,\n            )\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/interceptors/validator_request_interceptor.py#L86-L122","documentation":"Raised by ValidatorRequestInterceptor before the LLM is called when the last user message contains more AudioBlocks than the model supports. The interceptor collects audio blocks from the last user message, checks audio support via supports_audio(), then compares the count against max_audios_supported(llm, model_config). It is a client-side request validation error (Errors.InvalidRequest with code INVALID_REQUEST_AUDIO_MAX_NUM_ERROR).","triggerScenarios":"POST /v1/chat/completions (or the chat facade) with a ChatMessage whose blocks include more AudioBlock instances than the configured model's audio limit; e.g. attaching 3 audio clips to a model that supports 1.","commonSituations":"Switching from a multimodal model (high audio limit) to a text-only or single-audio model without trimming attachments; UI allowing unlimited audio uploads while the backend model config declares a small max; batch transcription-style requests stuffing many audios into one message.","solutions":["Reduce the number of AudioBlocks in the last user message to at most max_audios_supported() for the configured model.","Check max_audios_supported(llm, model_config) client/server-side before building the message and split extra audios into separate requests.","Switch to a model configuration that supports the required number of audio inputs.","If the limit reported is 0, verify the model config actually enables audio (otherwise error 359 INVALID_REQUEST_AUDIO_SUPPORT_ERROR applies instead)."],"exampleFix":"// before\nmsg = ChatMessage(role=MessageRole.USER, blocks=[TextBlock(text='transcribe these'), *audio_blocks])  // 5 audios, model supports 1\n\n// after\naudio_blocks = audio_blocks[:max_audios_supported(llm, model_config)]\nmsg = ChatMessage(role=MessageRole.USER, blocks=[TextBlock(text='transcribe this'), *audio_blocks])","handlingStrategy":"validation","validationCode":"from private_gpt.ui.helpers import max_audios_supported  # or the module where it lives\ncount = sum(isinstance(b, AudioBlock) for b in last_user_message.blocks)\nassert count <= max_audios_supported(llm, model_config), 'too many audios'","typeGuard":"def within_audio_limit(msg: ChatMessage, limit: int) -> bool:\n    return sum(isinstance(b, AudioBlock) for b in msg.blocks) <= limit","tryCatchPattern":"try:\n    await chat_facade.create_chat_event_generator(request=request)\nexcept Errors.InvalidRequest as e:\n    if e.code == Errors.Codes.INVALID_REQUEST_AUDIO_MAX_NUM_ERROR:\n        audios = audios[:max_audios_supported(llm, model_config)]  # trim and retry once","preventionTips":["Cap audio attachments in the UI at max_audios_supported for the active model","Validate block counts before submitting the request","Read the model's multimodal limits from model_config at startup"],"tags":["validation","multimodal","audio","chat","request"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}