invoke-ai/InvokeAI · error · HTTPException

Video URLs not found

Error message

Video URLs not found

What it means

HTTP 404 raised by get_video_urls in the videos router when generating URLs for a video fails for any reason. The handler wraps ApiDependencies.invoker.services.videos.get_url (for both video and thumbnail) in try/except and converts any exception into a bare 404. Because the except clause swallows the original exception, the underlying cause (missing file, bad service config) is lost.

Source

Thrown at invokeai/app/api/routers/videos.py:729

    return Response(
        thumbnail,
        media_type="image/webp",
        headers={"Cache-Control": _get_video_cache_control()},
    )


@videos_router.get("/i/{video_name}/urls", operation_id="get_video_urls", response_model=VideoUrlsDTO)
def get_video_urls(
    current_user: CurrentUserOrDefault,
    video_name: str = PathParam(description="The name of the video whose URL to get"),
) -> VideoUrlsDTO:
    _assert_video_read_access(video_name, current_user)
    try:
        video_url = ApiDependencies.invoker.services.videos.get_url(video_name)
        thumbnail_url = ApiDependencies.invoker.services.videos.get_url(video_name, thumbnail=True)
        return VideoUrlsDTO(video_name=video_name, video_url=video_url, thumbnail_url=thumbnail_url)
    except Exception:
        raise HTTPException(status_code=404)


@videos_router.get("/", operation_id="list_video_dtos", response_model=OffsetPaginatedResults[VideoDTO])
def list_video_dtos(
    current_user: CurrentUserOrDefault,
    video_origin: Optional[ResourceOrigin] = Query(default=None, description="The origin of videos to list."),
    categories: Optional[list[ImageCategory]] = Query(default=None, description="The categories of video to include."),
    is_intermediate: Optional[bool] = Query(default=None, description="Whether to list intermediate videos."),
    board_id: Optional[str] = Query(
        default=None,
        description="The board id to filter by. Use 'none' to find videos without a board.",
    ),
    # Bounds matter: these flow verbatim into SQL, and a negative LIMIT means
    # *unlimited* in SQLite — one request would materialize every video row.
    offset: int = Query(default=0, ge=0, description="The page offset"),
    limit: int = Query(default=10, ge=0, le=MAX_PAGE_SIZE, description="The number of videos per page"),
    order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
    starred_first: bool = Query(default=True, description="Whether to sort by starred videos first"),

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify the video_name exists by listing videos (GET /api/v1/videos) before requesting URLs
  2. Check the video file actually exists in the configured storage location (mounted volume, correct path)
  3. Log the swallowed exception server-side to see the real cause (the handler hides it)
  4. Restore the missing file or delete the orphaned record, then retry

Example fix

// before
video_url = ApiDependencies.invoker.services.videos.get_url(bad_name)
// after
names = client.list_videos().items
if any(v.video_name == bad_name for v in names):
    urls = client.get_video_urls(bad_name)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify video exists before fetching URLs
const list = await fetch(`${base}/api/v1/videos?limit=100`).then(r => r.json());
const exists = list.items.some(v => v.video_name === videoName);
if (!exists) throw new Error(`video ${videoName} not in library`);

Try / catch

try {
  const urls = await fetch(`${base}/api/v1/videos/${encodeURIComponent(videoName)}/urls`);
  if (!urls.ok) {
    if (urls.status === 404) console.warn(`video ${videoName} missing; refreshing list`);
    return null;
  }
  return await urls.json();
} catch (e) { log(e); return null; }

Prevention

When it happens

Trigger: GET /api/v1/videos/{video_name}/urls where the video name does not exist, the underlying file was deleted from disk, or the video URL service throws while resolving the URL.

Common situations: Client holds a stale video_name after the video was deleted or pruned; file storage volume not mounted so the file is missing; typo'd video name (wrong extension or ID vs name confusion); database record exists but the binary is gone.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/b57bd12099506d96. Report an issue: GitHub.