Skip to content

[Bug]: Server crashes in update_default_project() if no TTY attached #3796

@un-def

Description

@un-def

Steps to reproduce

# compose.yaml
services:
  dstack:
    image: dstackai/dstack:0.20.17
    container_name: dstack
    volumes:
      - .dstack:/root/.dstack
  1. docker compose up
  2. Stop the server (Ctrl+C)
  3. rm .dstack/server/data/sqlite.db (new DB → new admin user → new user token → ~/.dstack/config.yaml needs update)
  4. docker compose up

Actual behaviour

No response

Expected behaviour

No response

dstack version

0.20.17

Server logs

Attaching to dstack
dstack  |      _     _             _
dstack  |   __| |___| |_ __ _  ___| | __  ___  ___ _ ____   _____ _ __
dstack  |  / _` / __| __/ _` |/ __| |/ / / __|/ _ \ '__\ \ / / _ \ '__|
dstack  | | (_| \__ \ || (_| | (__|   <  \__ \  __/ |   \ V /  __/ |
dstack  |  \__,_|___/\__\__,_|\___|_|\_\ |___/\___|_|    \_/ \___|_|
dstack  |
dstack  | {"timestamp": "2026-04-20 13:24:08,812", "logger": "dstack._internal.server.services.events", "level": "INFO", "message": "Emitting event: User created. Event targets: user(8328fb)admin. Actor: user(8328fb)admin"}
dstack  | {"timestamp": "2026-04-20 13:24:08,845", "logger": "dstack._internal.server.services.events", "level": "INFO", "message": "Emitting event: Project created. Event targets: project(5a1bd5)main. Actor: user(8328fb)admin"}
dstack  | {"timestamp": "2026-04-20 13:24:08,854", "logger": "dstack._internal.server.app", "level": "INFO", "message": "Applying [link=file:///root/.dstack/server/config.yml]~/.dstack/server/config.yml[/link]..."}
dstack  | ERROR:    Traceback (most recent call last):
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/starlette/routing.py", line 694, in lifespan
dstack  |     async with self.lifespan_context(app) as maybe_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/fastapi/routing.py", line 204, in merged_lifespan
dstack  |     async with original_context(app) as maybe_original_state:
dstack  |   File "/usr/local/lib/python3.11/contextlib.py", line 210, in __aenter__
dstack  |     return await anext(self.gen)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/dstack/_internal/server/app.py", line 161, in lifespan
dstack  |     update_default_project(
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/dstack/_internal/core/services/configs/__init__.py", line 102, in update_default_project
dstack  |     or confirm_ask(
dstack  |        ^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/dstack/_internal/cli/utils/common.py", line 107, in confirm_ask
dstack  |     return Confirm.ask(prompt=prompt, **kwargs)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/rich/prompt.py", line 149, in ask
dstack  |     return _prompt(default=default, stream=stream)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/rich/prompt.py", line 292, in __call__
dstack  |     value = self.get_input(self.console, prompt, self.password, stream=stream)
dstack  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/rich/prompt.py", line 211, in get_input
dstack  |     return console.input(prompt, password=password, stream=stream)
dstack  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dstack  |   File "/root/.local/share/uv/tools/dstack/lib/python3.11/site-packages/rich/console.py", line 2189, in input
dstack  |     result = input()
dstack  |              ^^^^^^^
dstack  | EOFError: EOF when reading a line
dstack  |
dstack  | ERROR:    Application startup failed. Exiting.
dstack  | Update the main project in ~/.dstack/config.yml? [y/n]:
dstack exited with code 3

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions