cocoindex-io/cocoindex · error · ValueError

An app named '{name}' is already registered in this environm

Error message

An app named '{name}' is already registered in this environment.

What it means

Environment.register_app keeps a name-keyed registry of Apps per environment and rejects duplicate names under a lock. Registering a second App with the same name would make lookups ambiguous, so a ValueError is raised.

Source

Thrown at python/cocoindex/_internal/environment.py:153

    __slots__ = ("_env_ref", "_app_registry", "_app_registry_lock")

    _env_ref: weakref.ReferenceType[Environment | LazyEnvironment]
    _app_registry: weakref.WeakValueDictionary[str, App[Any, Any]]
    _app_registry_lock: threading.Lock

    def __init__(self, env: Environment | LazyEnvironment) -> None:
        self._env_ref = weakref.ref(env)
        self._app_registry = weakref.WeakValueDictionary()
        self._app_registry_lock = threading.Lock()
        with _environment_info_lock:
            _environment_infos.append(self)

    def register_app(self, name: str, app: App[Any, Any]) -> None:
        """Register an app with this environment."""
        with self._app_registry_lock:
            if name in self._app_registry:
                raise ValueError(
                    f"An app named '{name}' is already registered in this environment."
                )
            self._app_registry[name] = app

    def get_apps(self) -> list[App[Any, Any]]:
        """Get all registered apps for this environment."""
        with self._app_registry_lock:
            return list(self._app_registry.values())

    @property
    def env(self) -> Environment | LazyEnvironment | None:
        """The environment, or None if it has been garbage collected."""
        return self._env_ref()

    @property
    def env_name(self) -> str | None:
        """The environment name, or None if it has been garbage collected."""
        env = self.env

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Use a unique app name per registration (e.g. include a timestamp or test id)
  2. Drop or close the existing app/environment before re-registering
  3. Reuse the already-registered App instead of creating a new one
  4. Call env.drop()/reset so the registry is cleared between runs

Example fix

# before
app = coco.App(coco.AppConfig(name="FilesTransform"), app_main)

# after (re-run-safe)
name = f"FilesTransform-{uuid.uuid4().hex[:8]}"
app = coco.App(coco.AppConfig(name=name), app_main)
Defensive patterns

Strategy: validation

Validate before calling

existing = {a.name for a in env.get_apps()}
assert app_name not in existing, f"app {app_name} already registered"

Try / catch

try:
    env.register_app(name, app)
except ValueError:
    app = env.get_apps()[[a.name for a in env.get_apps()].index(name)]  # reuse existing

Prevention

When it happens

Trigger: Constructing and registering coco.App(AppConfig(name="X"), ...) twice in the same Environment — e.g. re-running app setup in a notebook, a script that creates the App in a loop, or module re-import without clearing the environment.

Common situations: Jupyter notebook cell re-execution, test suites building apps per test with the same name, hot-reloading dev servers that re-run module code while the environment persists.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/b7d1d645c70ecd57. Report an issue: GitHub.