immich-app/immich · warning · HTTPException

Task of type depends on output of

Error message

Task {entry['task']} of type {entry['type']} depends on output of {dep}

What it means

_run_inference executes each requested model task in order; a model may declare dependencies on outputs of earlier tasks (e.g. face detection feeding facial recognition). If a dependency's output is missing from the outputs map (KeyError), it raises HTTP 400 naming the task, type, and missing dependency.

Solutions

  1. Include all prerequisite tasks in the request config in the correct order (e.g. both face-detection and facial-recognition).
  2. Use the server-provided config rather than hand-crafted ones so dependencies are always present.
  3. Ensure server and ML service versions match so generated configs include required tasks.

Example fix

# before
{"facial-recognition": {"detection": {}, "recognition": {}}}
# after (include detection task so its output exists)
{"face-detection": {"detection": {}}, "facial-recognition": {"detection": {}, "recognition": {}}}
Defensive patterns

Strategy: validation

Validate before calling

# ensure prerequisite tasks are present in the request config
required = {"face-detection", "facial-recognition"}
assert required <= set(config.keys()), f"missing deps: {required - set(config)}"

Try / catch

try:
    r = requests.post(f"{ml}/predict", json={"image": b64, "entries": config})
    r.raise_for_status()
except requests.HTTPError as e:
    if e.response.status_code == 400 and "depends on output of" in e.response.json().get("detail", ""):
        add_missing_task_and_retry(config)

Prevention

When it happens

Trigger: Requesting an inference config where a dependent task (e.g. facial-recognition) is listed without its prerequisite (e.g. face-detection) in the same request, or the prerequisite's output key differs from model.depends entries.

Common situations: Custom/simplified inference configs omitting the detection step; version mismatch where the server's config omits a task the ML service expects; typo in the dep name in a hand-written config.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/c5a0fbdcbda6bc00. Report an issue: GitHub.

Appendix: source

Thrown at machine-learning/immich_ml/main.py:199

    response = await run_inference(inputs, entries)
    return ORJSONResponse(response)


async def run_inference(payload: Image | str, entries: InferenceEntries) -> InferenceResponse:
    outputs: dict[ModelIdentity, Any] = {}
    response: InferenceResponse = {}

    async def _run_inference(entry: InferenceEntry) -> None:
        model = await model_cache.get(
            entry["name"], entry["type"], entry["task"], ttl=settings.model_ttl, **entry["options"]
        )
        inputs = [payload]
        for dep in model.depends:
            try:
                inputs.append(outputs[dep])
            except KeyError:
                message = f"Task {entry['task']} of type {entry['type']} depends on output of {dep}"
                raise HTTPException(400, message)
        model = await load(model)
        output = await run(model.predict, *inputs, **entry["options"])
        outputs[model.identity] = output
        response[entry["task"]] = output

    without_deps, with_deps = entries
    await asyncio.gather(*[_run_inference(entry) for entry in without_deps])
    if with_deps:
        await asyncio.gather(*[_run_inference(entry) for entry in with_deps])
    if isinstance(payload, Image):
        response["imageHeight"], response["imageWidth"] = payload.height, payload.width

    return response


async def run(func: Callable[..., T], *args: Any, **kwargs: Any) -> T:
    if thread_pool is None:
        return func(*args, **kwargs)

View on GitHub (pinned to e55ac299a4)