{"record":{"id":"52c0ab5d0b8dcd0c","repo":"BoundaryML/baml","slug":"either-base-url-or-both-resource-name-deployment-id-must-be","errorCode":null,"errorMessage":"Either base_url or both (resource_name, deployment_id) must be provided","messagePattern":"Either base_url or both \\(resource_name, deployment_id\\) must be provided","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs","lineNumber":33,"sourceCode":") -> Result<PostRequestProperties> {\n    // POST https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version={api-version}\n\n    let default_role = properties.pull_default_role(\"system\")?;\n    let allowed_metadata = properties.pull_allowed_role_metadata()?;\n\n    let base_url = properties.pull_base_url()?;\n    let resource_name = properties.remove_str(\"resource_name\")?;\n    let deployment_id = properties.remove_str(\"deployment_id\")?;\n    let api_version = properties.remove_str(\"api_version\")?;\n\n    // Ensure that either (resource_name, deployment_id) or base_url is provided\n    let base_url = match (base_url, resource_name, deployment_id) {\n        (Some(base_url), None, None) => base_url,\n        (None, Some(resource_name), Some(deployment_id)) => {\n            format!(\"https://{resource_name}.openai.azure.com/openai/deployments/{deployment_id}\")\n        }\n        _ => {\n            anyhow::bail!(\"Either base_url or both (resource_name, deployment_id) must be provided\")\n        }\n    };\n\n    let api_key = properties\n        .pull_api_key()?\n        .or_else(|| ctx.env.get(\"AZURE_OPENAI_API_KEY\").map(|s| s.to_string()));\n    let mut headers = properties.pull_headers()?;\n    if let Some(api_key) = &api_key {\n        headers.insert(\"API-KEY\".to_string(), api_key.clone());\n    }\n    let headers = headers;\n\n    let mut query_params = HashMap::new();\n    if let Some(v) = api_version {\n        query_params.insert(\"api-version\".to_string(), v.to_string());\n    };\n\n    let supported_request_modes = properties.pull_supported_request_modes()?;","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs#L15-L51","documentation":"When resolving Azure OpenAI client properties, BAML requires exactly one way to build the endpoint: either an explicit `base_url`, or both `resource_name` and `deployment_id` (from which the standard Azure URL is constructed). Supplying none of them, or a partial/mixed combination (e.g. base_url plus resource_name, or resource_name without deployment_id), makes the configuration ambiguous or incomplete, so resolve_properties fails fast with this bail.","triggerScenarios":"Configuring an `azure` OpenAI client in clients.baml where: (a) none of base_url/resource_name/deployment_id are set; (b) only resource_name is set without deployment_id; (c) only deployment_id is set; (d) base_url is combined with resource_name and/or deployment_id (the match arms require None for the others).","commonSituations":"Copying an Azure client config from docs but forgetting the deployment_id; switching from the URL-based form to resource_name form and leaving a stale base_url; env-var-driven configs where AZURE_OPENAI_API_KEY is set but the endpoint fields were never provided; typos in property names so the fields resolve to None.","solutions":["Set both resource_name and deployment_id on the Azure client (and remove base_url if present).","Alternatively set a single base_url property and remove resource_name/deployment_id.","Verify property names are spelled exactly (base_url, resource_name, deployment_id) so the values are actually pulled.","If using Azure OpenAI via a proxy/gateway, provide its full base_url instead of the Azure resource fields."],"exampleFix":"// before\nclient<MyAzure> {\n  provider azure-openai\n  options {\n    resource_name \"my-res\"\n    api_key env.AZURE_OPENAI_API_KEY\n  }\n}\n// after\nclient<MyAzure> {\n  provider azure-openai\n  options {\n    resource_name \"my-res\"\n    deployment_id \"my-gpt4o\"\n    api_key env.AZURE_OPENAI_API_KEY\n  }\n}","handlingStrategy":"validation","validationCode":"// Go-style check before constructing the Azure client options\nfunc validateAzureOpts(baseURL, resourceName, deploymentID string) error {\n    hasURL := baseURL != \"\"\n    hasName := resourceName != \"\"\n    hasDep := deploymentID != \"\"\n    if hasURL && (hasName || hasDep) {\n        return fmt.Errorf(\"use either base_url OR (resource_name + deployment_id), not both\")\n    }\n    if !hasURL && !(hasName && hasDep) {\n        return fmt.Errorf(\"azure client needs base_url or both resource_name and deployment_id\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one endpoint style per Azure client and document it in clients.baml comments.","Never mix base_url with resource_name/deployment_id in the same options block.","When sourcing values from env vars, assert they are non-empty at startup."],"tags":["azure","config","openai","baml"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}