{"record":{"id":"e39367f046e71f04","repo":"BerriAI/litellm","slug":"max-retries-must-be-an-int","errorCode":null,"errorMessage":"max retries must be an int","messagePattern":"max retries must be an int","errorType":"exception","errorClass":"AzureOpenAIError","httpStatus":422,"severity":"error","filePath":"litellm/llms/azure/azure.py","lineNumber":329,"sourceCode":"                    litellm_params=litellm_params,\n                )\n            else:\n                ## LOGGING\n                logging_obj.pre_call(\n                    input=messages,\n                    api_key=api_key,\n                    additional_args={\n                        \"headers\": {\n                            \"api_key\": api_key,\n                            \"azure_ad_token\": azure_ad_token,\n                        },\n                        \"api_version\": api_version,\n                        \"api_base\": api_base,\n                        \"complete_input_dict\": data,\n                    },\n                )\n                if not isinstance(max_retries, int):\n                    raise AzureOpenAIError(status_code=422, message=\"max retries must be an int\")\n                # init AzureOpenAI Client\n                azure_client: Final = self.get_azure_openai_client(\n                    api_version=api_version,\n                    api_base=api_base,\n                    api_key=api_key,\n                    model=model,\n                    client=client,\n                    _is_async=False,\n                    litellm_params=litellm_params,\n                )\n                if not isinstance(azure_client, (AzureOpenAI, OpenAI)):\n                    raise AzureOpenAIError(\n                        status_code=500,\n                        message=\"azure_client is not an instance of AzureOpenAI or OpenAI\",\n                    )\n\n                headers, response = self.make_sync_azure_openai_chat_completion_request(\n                    azure_client=azure_client, data=data, timeout=timeout","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure/azure.py#L311-L347","documentation":"Before constructing the sync Azure OpenAI client, LiteLLM pops `max_retries` from optional_params and requires it to be an int (None falls back to the default, so unset is fine). Any other type — string, float, bool-like objects — raises this 422. This protects the underlying OpenAI SDK, which type-checks the value.","triggerScenarios":"Passing max_retries='3' (string from env/config), max_retries=3.0 (float), or max_retries=[3] to litellm.completion with an azure model.","commonSituations":"Reading retry counts from environment variables or YAML config which arrive as strings; JSON configs where the value was quoted.","solutions":["Pass max_retries as an int: max_retries=3.","Coerce config values at load time: int(os.environ.get('MAX_RETRIES', 2)).","Or omit max_retries entirely to use LiteLLM's default."],"exampleFix":"# before\nlitellm.completion(model=..., messages=msgs, max_retries=os.environ['MAX_RETRIES'])\n\n# after\nlitellm.completion(model=..., messages=msgs, max_retries=int(os.environ.get('MAX_RETRIES', 2)))","handlingStrategy":"type-guard","validationCode":"raw = config.get('max_retries')\nmax_retries = int(raw) if raw is not None else None  # None -> litellm default","typeGuard":"def is_valid_max_retries(v) -> bool:\n    return v is None or (isinstance(v, int) and not isinstance(v, bool))","tryCatchPattern":null,"preventionTips":["Coerce env/config strings to int at load time, never at call time.","Remember booleans are ints in Python — reject bool explicitly if you validate types yourself."],"tags":["azure","openai","type-error","configuration"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}