iOfficeAI/OfficeCLI · error · ArgumentException

Cannot determine image type from URL: {url}. Specify format

Error message

Cannot determine image type from URL: {url}. Specify format via file extension or content-type header.

What it means

Thrown by ImageSource.ResolveUrl as a last resort when the image type cannot be determined by any of the three fallback methods: (1) the server's Content-Type header didn't map to a known MIME type, (2) the URL path has no file extension or an unrecognized one, and (3) magic-byte sniffing on the downloaded bytes failed. The error includes the URL so the user can inspect it manually.

Source

Thrown at src/officecli/Core/ImageSource.cs:183

        var bytes = SsrfGuard.ReadBounded(response.Content.ReadAsStream(), SsrfGuard.MaxRemoteBytes, url, "image");
        var stream = new MemoryStream(bytes);

        // Try content-type header first
        var serverMime = response.Content.Headers.ContentType?.MediaType;
        if (!string.IsNullOrEmpty(serverMime) && TryMimeToContentType(serverMime, out var ct))
            return (stream, ct);

        // Fallback: extract extension from URL path (strip query string)
        var uri = new Uri(url);
        var ext = Path.GetExtension(uri.AbsolutePath);
        if (!string.IsNullOrEmpty(ext))
            return (stream, ExtensionToContentType(ext));

        // Last resort: sniff magic bytes
        if (TrySniffContentType(bytes, out var sniffed))
            return (stream, sniffed);

        throw new ArgumentException($"Cannot determine image type from URL: {url}. Specify format via file extension or content-type header.");
    }

    private static PartTypeInfo MimeToContentType(string mime)
    {
        if (TryMimeToContentType(mime, out var ct)) return ct;
        throw new ArgumentException($"Unsupported MIME type: {mime}. Supported: image/png, image/jpeg, image/gif, image/bmp, image/tiff, image/svg+xml");
    }

    private static bool TryMimeToContentType(string mime, out PartTypeInfo contentType)
    {
        contentType = mime.ToLowerInvariant() switch
        {
            "image/png" => ImagePartType.Png,
            "image/jpeg" or "image/jpg" => ImagePartType.Jpeg,
            "image/gif" => ImagePartType.Gif,
            "image/bmp" => ImagePartType.Bmp,
            "image/tiff" or "image/tif" => ImagePartType.Tiff,
            "image/svg+xml" => ImagePartType.Svg,

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a URL that ends in a recognized image extension (e.g. append '.png' if the server ignores it).
  2. Ensure the server sends a correct Content-Type header (image/png, image/jpeg, etc.).
  3. Download the file manually, determine its type, rename with the correct extension, and embed as a local file.
  4. If the server only supports octet-stream, download the bytes and use a local file with the correct extension.

Example fix

// before — no extension, no content-type
add image src='https://api.example.com/render?id=42' path='/body'

// after — download locally, add correct extension
// curl -o /tmp/img.png 'https://api.example.com/render?id=42'
// file /tmp/img.png  → verify it's actually PNG
add image src='/tmp/img.png' path='/body'
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check: ensure URL has a recognizable extension or known content-type
var uri = new Uri(url);
string ext = Path.GetExtension(uri.AbsolutePath);
var knownExts = new HashSet<string> { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tif", ".tiff", ".emf", ".wmf", ".svg" };
if (string.IsNullOrEmpty(ext) || !knownExts.Contains(ext.ToLowerInvariant()))
{
    Console.Error.WriteLine($"URL has no recognized image extension. Download locally or ensure server sends Content-Type.");
    // Download and embed as local file instead
    return;
}

Try / catch

try
{
    var (stream, contentType) = ImageSource.Resolve(url);
}
catch (ArgumentException ex) when (ex.Message.Contains("Cannot determine image type"))
{
    // Download the file, detect type, add extension, embed locally
}

Prevention

When it happens

Trigger: Fetching a URL like 'https://example.com/generate-image?id=42' where: the server sends no Content-Type or sends 'application/octet-stream', the URL path has no extension (the query string is stripped), and the downloaded bytes don't match any known image magic sequence. This is the final fallback after TryMimeToContentType, ExtensionToContentType, and TrySniffContentType all fail.

Common situations: A dynamically-generated image endpoint with no file extension in the URL. A CDN or proxy that strips Content-Type headers. A server that serves the image with 'application/octet-stream' or 'application/binary'. A URL that redirects to a different resource than expected.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/d20ceb0f2e614ba0. Report an issue: GitHub.