Correct logging setup for LangGraph - Getting I/O errors

What’s the correct way to set up logging in LangGraph? I’m getting frequent I/O errors when the application tries to log during async operations:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1113, in emit
    stream.write(msg + self.terminator)
ValueError: I/O operation on closed file.
...
  File "/usr/local/lib/python3.11/site-packages/httpx/_client.py", line 1740, in _send_single_request
    logger.info(
Message: 'HTTP Request: %s %s "%s %d %s"'
Arguments: ('POST', URL('https://api.openai.com/v1/chat/completions'), 'HTTP/1.1', 200, 'OK')

This happens when httpx tries to log OpenAI API responses within LangGraph workflows.

What’s the recommended approach for configuring loggers in LangGraph to avoid these issues?

I’m assuming you’re talking about langgraph platform? Since langgraph is just an OSS lib.

If the former, you can use stdlib or structlog regularly:

import logging

logger = logging.getLogger(__name__)
logger.info(“hi”)

or with structlog

import structlog
logger = structlog.stdlib.get_logger(__name__)
logger.info(“hi”, some_key=some_val)

I’m using both the LangGraph platform and local development. I’ve implemented the logger as suggested with an additional SafeStreamHandler to handle stream issues, but the error persists:

python

import logging
import sys

class SafeStreamHandler(logging.StreamHandler):
    def emit(self, record):
        try:
            super().emit(record)
        except (ValueError, OSError):
            pass

logger = logging.getLogger(__name__)
logger.handlers.clear()
handler = SafeStreamHandler(sys.stdout)
logger.addHandler(handler)

Any other suggestions for resolving this logging issue?

Interesting discussion. I’ve been experimenting with a slightly different angle on logging in LangGraph.

Instead of trying to capture everything (which can get noisy and brittle), I’ve been testing “collapse-point logging” — only recording when reasoning fails (contradictions, skipped steps, unknowns).

This produces a compact audit trail and reduces I/O churn, since you’re not writing every event — just the meaningful failure points.

Has anyone here tried a similar “failure-only” logging pattern with LangGraph?