microsoft/markitdown · error · ValueError

Failed to resolve analyzer

Error message

Failed to resolve analyzer '{analyzer_id}': {exc}

What it means

ContentUnderstandingConverter resolves the modality of a custom (or unknown prebuilt) analyzer by calling client.get_analyzer(analyzer_id). Any exception from that Azure Content Understanding call — auth failure, 404 for a nonexistent analyzer, network/DNS error — is wrapped in ValueError with the analyzer id and the underlying message, chained via 'from exc'. Known prebuilt ids bypass the call entirely (cache hit).

Solutions

  1. Check the chained exception ('from exc') — a 404 means the id/resource is wrong; 401/403 means credentials
  2. Verify the analyzer id and that it belongs to the endpoint's resource (list analyzers in the Azure portal or via the SDK)
  3. Confirm credential setup: AZURE_API_KEY / DefaultAzureCredential login, and the correct CU endpoint
  4. If network-bound, retry once connectivity is restored (the call happens once at converter init)

Example fix

# before
conv = ContentUnderstandingConverter(analyzer_id="my-analyzer")  # ValueError: Failed to resolve analyzer

# after
from azure.ai.contentsafety import ...  # verify via SDK/portal first:
# client.list_analyzers() -> confirm id exists
conv = ContentUnderstandingConverter(analyzer_id="my-analyzer-corrected")
Defensive patterns

Strategy: try-catch

Validate before calling

def analyzer_exists(client, analyzer_id: str) -> bool:
    try:
        client.get_analyzer(analyzer_id)
        return True
    except Exception:
        return False

Try / catch

try:
    conv = ContentUnderstandingConverter(analyzer_id=analyzer_id, client=client)
except ValueError as e:
    if "Failed to resolve analyzer" in str(e):
        log.error("analyzer %s unresolvable: %s", analyzer_id, e.__cause__)
        # fall back to default prebuilt analyzers (analyzer_id=None)
        conv = ContentUnderstandingConverter(client=client)
    else:
        raise

Prevention

When it happens

Trigger: Constructing ContentUnderstandingConverter(analyzer_id='my-custom-analyzer') when the analyzer does not exist in the resource, the credential lacks permissions, the endpoint/credential is misconfigured, or the network is unreachable.

Common situations: Typos in analyzer_id, using an analyzer from a different Azure resource, expired service-principal secrets, or a correct id but environment variables (endpoint/keys) pointing at the wrong resource.

Related errors


AI-assisted analysis of microsoft/markitdown@fd239d5d2b (2026-08-14). Data as JSON: /api/errors/1a6cbd86cbe2bafb. Report an issue: GitHub.

Appendix: source

Thrown at packages/markitdown/src/markitdown/converters/_cu_converter.py:422

    Args:
        client: A ``ContentUnderstandingClient`` instance.
        analyzer_id: The analyzer ID to resolve.

    Returns:
        Modality string ("document", "image", "audio", or "video").

    Raises:
        ValueError: If ``get_analyzer()`` fails.
    """
    # Known prebuilt — use cache, no API call
    if analyzer_id in _KNOWN_PREBUILT_MODALITY:
        return _KNOWN_PREBUILT_MODALITY[analyzer_id]

    # Unknown prebuilt or custom analyzer — call get_analyzer()
    try:
        analyzer_info = client.get_analyzer(analyzer_id)
    except Exception as exc:
        raise ValueError(f"Failed to resolve analyzer '{analyzer_id}': {exc}") from exc

    if analyzer_info.base_analyzer_id:
        return _BASE_TO_MODALITY.get(analyzer_info.base_analyzer_id, "document")
    return "document"


def _is_analyzer_compatible(file_modality: str, analyzer_modality: str) -> bool:
    """Return True when an analyzer modality can process a file modality."""
    if analyzer_modality == "document":
        return file_modality in {"document", "image"}
    return file_modality == analyzer_modality


# ---------------------------------------------------------------------------
# Converter
# ---------------------------------------------------------------------------

View on GitHub (pinned to fd239d5d2b)