ZhuLinsen/daily_stock_analysis · error · HTTPException

share_image_unavailable

share_image_unavailable

Error message

分享图片生成失败,请检查 {engine} 转图工具是否已安装并可用

What it means

503 share_image_unavailable from GET /history/{record_id}/share-image (the PNG endpoint, distinct from the HTML one). The handler calls markdown_to_image(...) which shells out to an external converter — the engine named by config.md2img_engine, default 'wkhtmltoimage'. When markdown_to_image returns None (engine binary missing, not executable, or failed to run), the endpoint returns 503 telling you to install/check the {engine} tool. It is an environment problem, not a data problem.

Source

Thrown at api/v1/endpoints/history.py:895

    },
    summary="生成历史报告分享图片",
    description="根据历史报告 Markdown 与持久化结构化数据生成确定性的 PNG 分享图片",
)
def get_history_share_image(
    record_id: str,
    db_manager: DatabaseManager = Depends(get_database_manager),
) -> Response:
    result, markdown_content = _history_share_image_input(record_id, db_manager)

    config = get_config()
    image_bytes = markdown_to_image(
        markdown_content,
        max_chars=getattr(config, "markdown_to_image_max_chars", 15000),
        structured_payload=_history_share_image_payload(result),
    )
    if image_bytes is None:
        engine = getattr(config, "md2img_engine", "wkhtmltoimage")
        raise HTTPException(
            status_code=503,
            detail={
                "error": "share_image_unavailable",
                "message": f"分享图片生成失败,请检查 {engine} 转图工具是否已安装并可用",
            },
        )

    filename = f"dsa-report-{result.get('id') or record_id}.png"
    return Response(
        content=image_bytes,
        media_type="image/png",
        headers={
            "Content-Disposition": f'attachment; filename="{filename}"',
            "Cache-Control": "no-store",
            "X-Content-Type-Options": "nosniff",
        },
    )

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Install the engine named in the message: e.g. apt-get install -y wkhtmltoimage (or xfonts + libxrender1 for headless rendering in slim images).
  2. Verify the server process can find it: `which wkhtmltoimage` under the same user/env the API runs.
  3. Alternatively switch config md2img_engine to an available engine supported by markdown_to_image and restart.
  4. In Docker-based deployments, add the install step to the image build rather than the running container.

Example fix

# before: Dockerfile with no converter
RUN pip install -r requirements.txt

# after
RUN apt-get update && apt-get install -y --no-install-recommends wkhtmltopdf xvfb libxrender1 fontconfig xfonts-base \
    && rm -rf /var/lib/apt/lists/*
RUN pip install -r requirements.txt
Defensive patterns

Strategy: fallback

Validate before calling

// capability probe before offering PNG share
async function engineAvailable() {
  try { await fetchPngShare(knownSmallReportId); return true; }
  catch (e) { return !isHttp503(e); }
}

Try / catch

try { png = await getPngShare(id); }
catch (e) {
  if (isHttp503(e) && e.code === 'share_image_unavailable') {
    png = await renderLocally(await getShareHtml(id)); // desktop-side screenshot fallback
  }
}

Prevention

When it happens

Trigger: wkhtmltoimage (or the configured md2img_engine) not installed in the container/host; binary present but not on PATH for the server process; missing runtime dependencies of the engine (X11 libs for wkhtmltoimage in slim Docker images); engine crashing on specific input so the wrapper returns None.

Common situations: Docker/slim deployments that never installed the converter; macOS/Windows local runs where the binary name differs; CI environments lacking the tool; PATH differences between the shell used to install and the service process.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/1eda6b9aa77dd213. Report an issue: GitHub.