Files
ComfyUI-Lora-Manager/docs/recipe-civitai-image-no-metadata.md
T
Will Miao a17399d667 feat(recipes): delegate CivitAI-image re-import to companion browser extension
Recipes imported from CivitAI image URLs can contain 0 LoRAs: the backend
only sees the REST image API + EXIF, while the complete generation data
lives in the image page's internal trpc payload (see
docs/recipe-civitai-image-no-metadata.md). When the companion
lm-civitai-extension is installed with a valid license, re-import (single
and bulk) of CivitAI-image-sourced recipes is now delegated to the
extension via DOM CustomEvents; the extension scrapes the image page with
the user's session and calls back into the reimport endpoint with the
full metadata payload. Without the extension (or with an invalid license)
the native path runs unchanged.

- POST /api/lm/recipe/{id}/reimport accepts optional payload params
  (image_url/name/resources/gen_params/base_model/tags); the payload path
  reuses the import-remote engine with reimport semantics (user-edit
  carryover, delete-after-save), and malformed/failed payloads fall back
  to the legacy URL import. Response gains loras_count.
- The endpoint also accepts GET: the extension is GET-only by convention
  (documented in AGENTS.md).
- New static/js/utils/extensionReimportBridge.js (probeExtension /
  delegateReimport / getCivitaiImageInfo) wired into RecipeContextMenu
  and BulkManager with silent native fallback.
- i18n: toast.recipes.reimportingViaExtension added and translated in
  all 9 locales.
2026-09-06 20:26:14 +08:00

2.8 KiB

CivitAI image imports can end up with 0 LoRAs

Symptom

Importing a CivitAI image URL can produce a recipe with zero LoRA entries, even though the image page lists LoRAs in its resource panel.

Reported example: https://civitai.red/images/140818889 was imported as a local recipe with 0 LoRAs, while the page shows 3 LoRAs. Some images (e.g. NSFW / higher browsing level) additionally require a login to view, so their data is not publicly reachable at all.

Root cause

URL imports use only two data sources:

  1. CivitAI REST image APIGET /api/v1/images?imageId=<id>&nsfw=X&withMeta=truemeta
  2. Embedded image metadata — EXIF/XMP read from the downloaded bytes

For the same image both sources can be empty, and the one source that does contain the data is never queried. Verified for image 140818889:

Source What it returned
REST image API meta holds only a prompt; modelVersionIds: []; no resources/hashes; baseModel: null
Downloaded image PNG with no EXIF/XMP (the CDN URL ends in .jpeg, the body is PNG)
Image page HTML __NEXT_DATA__ embeds the trpc image.getGenerationData result → full resources list: 3 LoRAs, each with modelId, modelVersionId, modelName, modelType, versionName, baseModel

Key points:

  • The page's resource panel is fed by an internal, non-public trpc endpoint, not by the public REST image API.
  • That internal endpoint is login-gated for some content — the "requires login" symptom.
  • Even with the version IDs in hand, /model-versions/{id} for these (Krea) versions returns no sha256, so an exact local-file hash match is impossible; only model/version identity is recoverable.

Conclusion / status

0-LoRA imports are a data-source gap: public REST meta and image EXIF are both empty, while the only complete source (page generation data) is internal, sometimes login-gated, and not used by the importer.

Such imports cannot be reliably auto-repaired/completed by the backend alone. The old "Repair Metadata" feature only re-fetched the same incomplete REST meta and could not fix them; it was deprecated and has been removed.

Fixed via the companion browser extension. When the extension is installed with a valid license, it scrapes the image page's internal trpc generation data with the user's session and calls the payload-capable re-import endpoint (POST /api/lm/recipe/{recipe_id}/reimport with image_url/name/resources/gen_params/base_model/tags query params), which rebuilds the recipe from the caller-supplied metadata. The web UI delegates re-import of CivitAI-image-sourced recipes to the extension automatically (probe + lm:reimport* DOM events); without the extension, re-import silently falls back to the native path, which remains limited by the data-source gap documented above.