Skip to content

[starIdentifier] image fetches fail with auth enabled — urllib calls don't pass session cookie #717

Description

@Mavrx-Operations

Plugin

plugins/starIdentifierstar_identifier.py

Bug

The plugin fetches performer images and scene screenshots via raw urllib.request.urlopen():

# line ~189
image = face_recognition.load_image_file(urllib.request.urlopen(performer['image_path']))

# line ~202
image = urllib.request.urlopen(scene['paths']['screenshot'])

Neither call attaches the session cookie Stash hands plugins via json_input["server_connection"]["SessionCookie"]["Value"]. With Stash configured to require authentication (username + password set in config.yml), every urlopen returns the login page HTML instead of the image, and PIL raises:

ERRO [Plugin / Star Identifier] cannot identify image file <_io.BytesIO object at 0x...>

Export Performers writes no encodings file, and the subsequent identify task then fails with:

Encoding database not found at .../star-identifier-encodings/star-identifier-encodings.npz.
Run Export Performers and try again.

Without auth (the unsecured deployment case) this path works by accident.

The plugin's IdentifierStashInterface class already receives and stores the session cookie — it's used for the GraphQL POST in __callGraphQL, just not for the image fetches.

Repro

  1. Configure Stash with username + password in config.yml.
  2. Install Star Identifier (assume [starIdentifier] manifest exec path references non-existent py_plugins/ subdirectory #716 patched / manifest fixed so the plugin can actually launch).
  3. Run Export Performers — every performer hits cannot identify image file.

Suggested fix

Module-global the cookie (so ProcessPoolExecutor workers inherit it via fork() on Linux) and route the two image fetches through a helper. Minimal patch:

# near the top, after the existing imports:
SESSION_COOKIE = None

def _open_with_cookie(url):
    req = urllib.request.Request(url)
    if SESSION_COOKIE:
        req.add_header("Cookie", f"session={SESSION_COOKIE}")
    return urllib.request.urlopen(req)

# inside run(), right after `client = IdentifierStashInterface(...)`:
global SESSION_COOKIE
SESSION_COOKIE = client.cookies.get("session")

# encode_performer_from_url + get_recognized_ids_from_scene_screenshot:
#   replace `urllib.request.urlopen(...)` calls with `_open_with_cookie(...)`

Verified locally — Export Performers now actually processes images and writes the .npz.

Portability note

This works because Python's ProcessPoolExecutor uses fork as the default start-method on Linux, and forked workers inherit module-level state set before the fork point. On spawn/forkserver (Windows; or if a future CPython release changes the default) the global wouldn't propagate. Passing the cookie as an explicit arg via executor.submit(fn, item, SESSION_COOKIE) is more portable but requires changing the call sites and the execute_identification_list harness signature.

Environment

  • Stash v0.31.1 (4de2351e)
  • Container: stashapp/stash:latest (Alpine, Python 3.12.13)
  • Plugin version: 1.0
  • Stash auth: username + password set in config.yml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions