zed-industries/zed · error · AppNotDeployedError

app '{args.app_name}' not deployed (or function '{function_n

Error message

app '{args.app_name}' not deployed (or function '{function_name}' missing) — run 'zed-eval deploy' first

What it means

Before a run, common.py hydrates modal.Function.from_name(app_name, function_name) and converts modal.exception.NotFoundError into AppNotDeployedError with the fix in the message. Hydration is eager on purpose: without it, the failure would surface mid-run inside .spawn()/.remote(); failing here avoids the other bad option (auto-deploying), because deploying would cancel in-flight runs.

Source

Thrown at crates/eval_cli/zed_eval/common.py:142


def deployed_function(args: argparse.Namespace, function_name: str):
    """Look up an already-deployed Modal function. Never deploys.

    `modal.Function.from_name` resolves a published function without deploying,
    which is exactly what we want: deploying would cancel in-flight runs. We
    hydrate eagerly so a missing app/function fails here with an actionable
    message instead of deep inside a later `.spawn()`/`.remote()` call.
    """
    import modal
    from modal.exception import NotFoundError

    configure_modal_environment(args)
    function = modal.Function.from_name(args.app_name, function_name)
    try:
        function.hydrate()
    except NotFoundError as error:
        raise AppNotDeployedError(
            f"app '{args.app_name}' not deployed (or function "
            f"'{function_name}' missing) — run 'zed-eval deploy' first"
        ) from error
    return function


def modal_call_id(call: Any) -> str:
    for attribute in ("object_id", "id", "function_call_id"):
        value = getattr(call, attribute, None)
        if value:
            return str(value)
    return str(call)


def print_table(rows: list[dict[str, Any]], columns: list[tuple[str, str]]) -> None:
    if not rows:
        print("No rows")
        return

View on GitHub (pinned to bc538def45)

Solutions

  1. Deploy first: `zed-eval deploy`, then re-run the command
  2. Confirm the client uses the same Modal token/environment/namespace the app was deployed under
  3. Verify the function_name being hydrated matches what deploy registered

Example fix

# before
zed-eval run ...   # AppNotDeployedError

# after
zed-eval deploy && zed-eval run ...
Defensive patterns

Strategy: try-catch

Validate before calling

import modal

async def deployed_apps():
    return {app.app_name async for app in modal.App.list()}

# before a batch job:
# if args.app_name not in await deployed_apps(): run `zed-eval deploy` first

Type guard

from modal.exception import NotFoundError

def is_deployed(function):
    try:
        function.hydrate()
        return True
    except NotFoundError:
        return False

Try / catch

from zed_eval.common import AppNotDeployedError

try:
    function = get_modal_function(args, "rollout")
except AppNotDeployedError as e:
    raise SystemExit(f"{e} — deploy, then re-run")

Prevention

When it happens

Trigger: Running eval commands against app_name before `zed-eval deploy` was ever executed in that environment/namespace; a client whose Modal token/environment (set by configure_modal_environment(args)) differs from where the app was deployed; the function label changing so from_name no longer resolves.

Common situations: Fresh machines or CI jobs skipping the deploy step; MODAL_ENVIRONMENT or token pointing at another account/namespace; stale deployments torn down by retention.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/de313a47a13c8a52. Report an issue: GitHub.