Unable to Execute langgraph up on Windows: NotImplementedError with asyncio Signal #4

Open
opened 2026-02-16 05:17:17 -05:00 by yindo · 4 comments
Owner

Originally created by @c0pper on GitHub (Jun 19, 2024).

Issue Summary:

Attempting to run langgraph up on Windows results in the following error:

Traceback (most recent call last):
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\exec.py", line 64, in subp_exec
    loop.add_signal_handler(signal.SIGINT, signal_handler)
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 574, in add_signal_handler
    raise NotImplementedError
NotImplementedError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "c:\workspace\python\delfi\.venv\Scripts\langgraph.exe\__main__.py", line 7, in <module>
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\cli.py", line 183, in up
    capabilities = langgraph_cli.docker.check_capabilities(runner)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\docker.py", line 83, in check_capabilities
    stdout, _ = runner.run(subp_exec("docker", "info", "-f", "json", collect=True))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\exec.py", line 103, in subp_exec
    os.killpg(os.getpgid(proc.pid), signal.SIGINT)
    ^^^^^^^^^
AttributeError: module 'os' has no attribute 'killpg'. Did you mean: 'kill'?
Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x000001B4EE7E6E80>
Traceback (most recent call last):
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_subprocess.py", line 126, in __del__
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_subprocess.py", line 104, in close
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 108, in close
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 758, in call_soon
  File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 519, in _check_closed
RuntimeError: Event loop is closed

Steps to Reproduce:

Ensure Docker Desktop is installed and running on Windows.
Activate Python environment (venv or virtualenv).
Install langgraph-cli using pip install langgraph-cli.
Run langgraph up command.

Expected Behavior:

The langgraph up command should start successfully and execute without errors, leveraging Docker functionality on Windows.

Actual Behavior:

Encountered a NotImplementedError related to add_signal_handler and subsequent errors related to os.killpg and Event loop is closed.

Environment Details:

Operating System: Windows 11
Python Version: 3.11

Additional Context:

I have Docker Desktop installed and running on my Windows machine. This issue prevents me from using langgraph-cli effectively for my development workflows.

Originally created by @c0pper on GitHub (Jun 19, 2024). ## Issue Summary: Attempting to run langgraph up on Windows results in the following error: ``` Traceback (most recent call last): File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\exec.py", line 64, in subp_exec loop.add_signal_handler(signal.SIGINT, signal_handler) File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 574, in add_signal_handler raise NotImplementedError NotImplementedError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "c:\workspace\python\delfi\.venv\Scripts\langgraph.exe\__main__.py", line 7, in <module> File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1157, in __call__ return self.main(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1078, in main rv = self.invoke(ctx) ^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1688, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 1434, in invoke return ctx.invoke(self.callback, **ctx.params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\click\core.py", line 783, in invoke return __callback(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\cli.py", line 183, in up capabilities = langgraph_cli.docker.check_capabilities(runner) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\docker.py", line 83, in check_capabilities stdout, _ = runner.run(subp_exec("docker", "info", "-f", "json", collect=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run return self._loop.run_until_complete(task) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "c:\workspace\python\delfi\.venv\Lib\site-packages\langgraph_cli\exec.py", line 103, in subp_exec os.killpg(os.getpgid(proc.pid), signal.SIGINT) ^^^^^^^^^ AttributeError: module 'os' has no attribute 'killpg'. Did you mean: 'kill'? Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x000001B4EE7E6E80> Traceback (most recent call last): File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_subprocess.py", line 126, in __del__ File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_subprocess.py", line 104, in close File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 108, in close File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 758, in call_soon File "C:\Users\smarotta\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 519, in _check_closed RuntimeError: Event loop is closed ``` ## Steps to Reproduce: Ensure Docker Desktop is installed and running on Windows. Activate Python environment (venv or virtualenv). Install langgraph-cli using pip install langgraph-cli. Run langgraph up command. ## Expected Behavior: The langgraph up command should start successfully and execute without errors, leveraging Docker functionality on Windows. ## Actual Behavior: Encountered a NotImplementedError related to add_signal_handler and subsequent errors related to os.killpg and Event loop is closed. ## Environment Details: Operating System: Windows 11 Python Version: 3.11 ## Additional Context: I have Docker Desktop installed and running on my Windows machine. This issue prevents me from using langgraph-cli effectively for my development workflows.
Author
Owner

@SouthCentralCode commented on GitHub (Jun 19, 2024):

Was having the same issue...

so created a very hacky workaround (using a cursor.so) to get it working on windows...

I changed my local \site-packages\langgraph_cli\exec.py

to the below code and it has worked to create the docker image and containers.

ive only ran it once, so be warned...

import asyncio
import os
import sys
from contextlib import contextmanager
from typing import Callable, Optional, cast

import click.exceptions


@contextmanager  
def Runner():
    if hasattr(asyncio, "Runner"):
        with asyncio.Runner() as runner:
            yield runner
    else:

        class _Runner:
            def __enter__(self):
                return self

            def __exit__(self, *args):
                pass

            def run(self, coro):
                asyncio.run(coro)

        yield _Runner()


async def subp_exec(
    cmd: str,
    *args: str,
    input: Optional[str] = None,
    wait: Optional[float] = None,
    verbose: bool = False,
    collect: bool = False,
    on_stdout: Optional[Callable[[str], Optional[bool]]] = None,
) -> tuple[Optional[str], Optional[str]]:
    if verbose:
        cmd_str = f"+ {cmd} {' '.join(map(str, args))}"
        if input:
            print(cmd_str, " <\n", "\n".join(filter(None, input.splitlines())), sep="")
        else:
            print(cmd_str)
    if wait:
        await asyncio.sleep(wait)

    try:
        proc = await asyncio.create_subprocess_exec(
            cmd,
            *args,
            stdin=asyncio.subprocess.PIPE if input else None,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )

        def signal_handler():
            # make sure process exists, then terminate it
            if proc.returncode is None:
                proc.terminate()

        loop = asyncio.get_event_loop()
        signal_handlers_installed = False
        if os.name != 'nt':  # Skip signal handling on Windows
            try:
                loop.add_signal_handler(signal.SIGINT, signal_handler)
                loop.add_signal_handler(signal.SIGTERM, signal_handler)
                signal_handlers_installed = True
            except NotImplementedError:
                pass

        empty_fut: asyncio.Future = asyncio.Future()
        empty_fut.set_result(None)
        stdout, stderr, _ = await asyncio.gather(
            monitor_stream(
                cast(asyncio.StreamReader, proc.stdout),
                collect=True,
                display=verbose,
                on_line=on_stdout,
            ),
            monitor_stream(
                cast(asyncio.StreamReader, proc.stderr),
                collect=True,
                display=verbose,
            ),
            proc._feed_stdin(input.encode()) if input else empty_fut,  # type: ignore[attr-defined]
        )
        returncode = await proc.wait()
        if (
            returncode is not None
            and returncode != 0  # success
            and returncode != 130  # user interrupt
        ):
            sys.stdout.write(stdout.decode() if stdout else "")
            sys.stderr.write(stderr.decode() if stderr else "")
            raise click.exceptions.Exit(returncode)
        if collect:
            return (
                stdout.decode() if stdout else None,
                stderr.decode() if stderr else None,
            )
        else:
            return None, None
    finally:
        try:
            if proc.returncode is None:
                try:
                    os.kill(proc.pid, signal.SIGINT)
                except (ProcessLookupError, KeyboardInterrupt):
                    pass

            if signal_handlers_installed:
                loop.remove_signal_handler(signal.SIGINT)
                loop.remove_signal_handler(signal.SIGTERM)
        except UnboundLocalError:
            pass


async def monitor_stream(
    stream: asyncio.StreamReader,
    collect: bool = False,
    display: bool = False,
    on_line: Optional[Callable[[str], Optional[bool]]] = None,
) -> Optional[bytearray]:
    if collect:
        ba = bytearray()

    def handle(line: bytes):
        nonlocal on_line
        nonlocal display

        if collect:
            ba.extend(line)
        if display:
            sys.stdout.write(line.decode())
        if on_line:
            if on_line(line.decode()):
                on_line = None
                display = True

    async for line in stream:
        await asyncio.to_thread(handle, line)
    if collect:
        return ba
    else:
        return None
@SouthCentralCode commented on GitHub (Jun 19, 2024): Was having the same issue... so created a very hacky workaround (using a cursor.so) to get it working on windows... I changed my local \site-packages\langgraph_cli\exec.py to the below code and it has worked to create the docker image and containers. ive only ran it once, so be warned... ``` import asyncio import os import sys from contextlib import contextmanager from typing import Callable, Optional, cast import click.exceptions @contextmanager def Runner(): if hasattr(asyncio, "Runner"): with asyncio.Runner() as runner: yield runner else: class _Runner: def __enter__(self): return self def __exit__(self, *args): pass def run(self, coro): asyncio.run(coro) yield _Runner() async def subp_exec( cmd: str, *args: str, input: Optional[str] = None, wait: Optional[float] = None, verbose: bool = False, collect: bool = False, on_stdout: Optional[Callable[[str], Optional[bool]]] = None, ) -> tuple[Optional[str], Optional[str]]: if verbose: cmd_str = f"+ {cmd} {' '.join(map(str, args))}" if input: print(cmd_str, " <\n", "\n".join(filter(None, input.splitlines())), sep="") else: print(cmd_str) if wait: await asyncio.sleep(wait) try: proc = await asyncio.create_subprocess_exec( cmd, *args, stdin=asyncio.subprocess.PIPE if input else None, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) def signal_handler(): # make sure process exists, then terminate it if proc.returncode is None: proc.terminate() loop = asyncio.get_event_loop() signal_handlers_installed = False if os.name != 'nt': # Skip signal handling on Windows try: loop.add_signal_handler(signal.SIGINT, signal_handler) loop.add_signal_handler(signal.SIGTERM, signal_handler) signal_handlers_installed = True except NotImplementedError: pass empty_fut: asyncio.Future = asyncio.Future() empty_fut.set_result(None) stdout, stderr, _ = await asyncio.gather( monitor_stream( cast(asyncio.StreamReader, proc.stdout), collect=True, display=verbose, on_line=on_stdout, ), monitor_stream( cast(asyncio.StreamReader, proc.stderr), collect=True, display=verbose, ), proc._feed_stdin(input.encode()) if input else empty_fut, # type: ignore[attr-defined] ) returncode = await proc.wait() if ( returncode is not None and returncode != 0 # success and returncode != 130 # user interrupt ): sys.stdout.write(stdout.decode() if stdout else "") sys.stderr.write(stderr.decode() if stderr else "") raise click.exceptions.Exit(returncode) if collect: return ( stdout.decode() if stdout else None, stderr.decode() if stderr else None, ) else: return None, None finally: try: if proc.returncode is None: try: os.kill(proc.pid, signal.SIGINT) except (ProcessLookupError, KeyboardInterrupt): pass if signal_handlers_installed: loop.remove_signal_handler(signal.SIGINT) loop.remove_signal_handler(signal.SIGTERM) except UnboundLocalError: pass async def monitor_stream( stream: asyncio.StreamReader, collect: bool = False, display: bool = False, on_line: Optional[Callable[[str], Optional[bool]]] = None, ) -> Optional[bytearray]: if collect: ba = bytearray() def handle(line: bytes): nonlocal on_line nonlocal display if collect: ba.extend(line) if display: sys.stdout.write(line.decode()) if on_line: if on_line(line.decode()): on_line = None display = True async for line in stream: await asyncio.to_thread(handle, line) if collect: return ba else: return None ```
Author
Owner

@c0pper commented on GitHub (Jun 20, 2024):

That did the trick, thanks a lot!

@c0pper commented on GitHub (Jun 20, 2024): That did the trick, thanks a lot!
Author
Owner

@ahsanshah commented on GitHub (May 24, 2025):

It seems like Langgraph is not useable in Windows (despite now we say we no longer need a Desktop App in a Mac and its compatible) has anyone addresses this issue cleanly on Windows or is the best way just avoid Windows for Langgraph.

@ahsanshah commented on GitHub (May 24, 2025): It seems like Langgraph is not useable in Windows (despite now we say we no longer need a Desktop App in a Mac and its compatible) has anyone addresses this issue cleanly on Windows or is the best way just avoid Windows for Langgraph.
Author
Owner

@icsimlai commented on GitHub (Sep 5, 2025):

@ahsanshah,
I was having the issue in Windows environment as below,
"langgraph : The term 'langgraph' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."

Then I created a ".venv" environment and opened the "Integrated Terminal" in it e.g., "...venv>"
After that I could execute all the below commands,

langgraph --version
LangGraph CLI, version 0.4.1
pip show langgraph
Name: langgraph
Version: 0.6.6
Summary: Building stateful, multi-actor applications with LLMs

langgraph --help
Usage: langgraph [OPTIONS] COMMAND [ARGS]...

Options:
--version Show the version and exit.
--help Show this message and exit.

Commands:
build 📦 Build LangGraph API server Docker image.
dev 🏃‍♀️‍➡️ Run LangGraph API server in development mode with...
dockerfile 🐳 Generate a Dockerfile for the LangGraph API server, with...
new 🌱 Create a new LangGraph project from a template.
up 🚀 Launch LangGraph API server.

@icsimlai commented on GitHub (Sep 5, 2025): @ahsanshah, I was having the issue in Windows environment as below, "_langgraph : The term 'langgraph' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again._" Then I created a ".venv" environment and opened the "Integrated Terminal" in it e.g., "..\.venv>" After that I could execute all the below commands, > langgraph --version LangGraph CLI, version 0.4.1 > pip show langgraph Name: langgraph Version: 0.6.6 Summary: Building stateful, multi-actor applications with LLMs > langgraph --help Usage: langgraph [OPTIONS] COMMAND [ARGS]... Options: --version Show the version and exit. --help Show this message and exit. Commands: build 📦 Build LangGraph API server Docker image. dev 🏃‍♀️‍➡️ Run LangGraph API server in development mode with... dockerfile 🐳 Generate a Dockerfile for the LangGraph API server, with... new 🌱 Create a new LangGraph project from a template. up 🚀 Launch LangGraph API server.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph-example#4