siyuan-note/siyuan · error

generated image URL must use HTTPS

Error message

generated image URL must use HTTPS

What it means

Thrown by downloadGeneratedImage (kernel/util/openai.go:783) when url.Parse fails OR the parsed scheme is not exactly 'https' OR the host is empty. SiYuan refuses plaintext HTTP and host-less URLs for generated-image downloads as a baseline transport-security guard, before the SSRF check (CheckHostSSRF) runs.

Source

Thrown at kernel/util/openai.go:783

	} else if result.URL != "" {
		data, err = downloadGeneratedImage(requestCtx, result.URL)
	} else {
		err = errors.New("image model returned neither base64 data nor URL")
	}
	if err != nil {
		return GeneratedImage{}, err
	}
	mimeType, extension, err := ValidateGeneratedImage(data)
	if err != nil {
		return GeneratedImage{}, err
	}
	return GeneratedImage{Data: data, MIMEType: mimeType, Extension: extension, RevisedPrompt: result.RevisedPrompt}, nil
}

func downloadGeneratedImage(ctx context.Context, rawURL string) ([]byte, error) {
	parsed, err := url.Parse(rawURL)
	if err != nil || parsed.Scheme != "https" || parsed.Host == "" {
		return nil, errors.New("generated image URL must use HTTPS")
	}
	if err = CheckHostSSRF(parsed.Hostname()); err != nil {
		return nil, err
	}
	client := generatedImageHTTPClient()
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
	if err != nil {
		return nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("download generated image failed with status %d", resp.StatusCode)
	}
	if resp.ContentLength > maxGeneratedImageBytes {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Confirm the provider/CDN is configured to serve image URLs over HTTPS end to end.
  2. If you operate the provider, force https in the URL generator.
  3. If only b64json is available from the provider, switch the request to ResponseFormat=b64_json to bypass the URL path entirely.
  4. Avoid proxies/env (HTTPS_PROXY) that downgrade the scheme.

Example fix

// before
result := response.Data[0]
if result.URL != "" {
    data, err = downloadGeneratedImage(requestCtx, result.URL)
}

// after (prefer b64json for providers known to return http URLs)
result := response.Data[0]
if result.B64JSON != "" {
    data, err = base64.StdEncoding.DecodeString(result.B64JSON)
} else if u, perr := url.Parse(result.URL); perr == nil && u.Scheme == "https" && u.Host != "" {
    data, err = downloadGeneratedImage(requestCtx, result.URL)
} else {
    err = fmt.Errorf("provider returned non-HTTPS image URL %q; enable b64_json", result.URL)
}
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(result.URL)
if err != nil || u.Scheme != "https" || u.Host == "" {
    // prefer b64_json delivery or refuse the URL
    return fmt.Errorf("refusing non-HTTPS image URL %q", result.URL)
}

Try / catch

data, err := downloadGeneratedImage(ctx, result.URL)
if err != nil && strings.Contains(err.Error(), "must use HTTPS") {
    // switch this provider to b64_json mode, or surface a config error
    imageRequest.ResponseFormat = openai.CreateImageResponseFormatB64JSON
    // ...re-issue CreateImage
}
if err != nil { return err }

Prevention

When it happens

Trigger: The image model returns a URL with scheme http://, ftp://, or a relative/malformed URL with no scheme; or url.Parse rejects the string. Also fires if a redirect target downgrades to http (caught again at the redirect hook, but this is the initial-parse guard).

Common situations: Older/self-hosted OpenAI-compatible provider returning http CDN URLs; provider CDN misconfigured to serve over http; proxy that rewrote https to http; provider returned a relative path by mistake.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/89206ce5d22e9f48. Report an issue: GitHub.