Skip to content

[BUG] Noisy ValueError tracebacks when CrewAI initialized from non-main thread #4289

@Bharath-designer

Description

@Bharath-designer

Description

When CrewAI is initialized from a thread other than the main thread (e.g., in Streamlit, Flask, Django, Jupyter, etc.), the telemetry module prints multiple ValueError tracebacks for each signal handler registration attempt. While these are caught and don't crash the application, they create confusing console output.

Steps to Reproduce

  1. Create a file reproduce.py with the following content:
import threading

def run_crewai_in_thread():
    from crewai import Agent  # Import triggers Telemetry singleton initialization
    
    print("CrewAI imported successfully in thread")

if __name__ == "__main__":
    print("Starting CrewAI import in non-main thread...\n")
    
    thread = threading.Thread(target=run_crewai_in_thread)
    thread.start()
    thread.join()
    
    print("\nDone")
  1. Run the script:
python reproduce.py
  1. Observe the output — multiple ValueError tracebacks are printed:
Starting CrewAI import in non-main thread...

Cannot register SIGTERM handler: not running in main thread
Traceback (most recent call last):
  File ".../crewai/telemetry/telemetry.py", line 214, in _register_signal_handler
    signal.signal(sig, handler)
ValueError: signal only works in main thread of the main interpreter

Cannot register SIGINT handler: not running in main thread
Traceback (most recent call last):
  ...
ValueError: signal only works in main thread of the main interpreter

(repeated for SIGHUP, SIGTSTP, SIGCONT)

CrewAI imported successfully in thread
Done.

Expected behavior

Starting CrewAI import in non-main thread...

CrewAI telemetry: Skipping signal handler registration (not running in main thread). To disable this warning or disable crewai telemetry entirely, set CREWAI_DISABLE_TELEMETRY=true. See: https://docs.crewai.com/telemetry

CrewAI imported successfully in thread
Done.

Screenshots/Code snippets

Image

Operating System

Other (specify in additional context)

Python Version

3.12

crewAI Version

1.9.0

crewAI Tools Version

1.9.0

Virtual Environment

Venv

Evidence

Image

Possible Solution

Proposed Solution

Add a proactive main thread check in _register_shutdown_handlers() before attempting signal registration.

File: src/crewai/telemetry/telemetry.py

Current code (lines 170-183):

def _register_shutdown_handlers(self) -> None:
    """Register handlers for graceful shutdown on process exit and signals."""
    atexit.register(self._shutdown)

    self._original_handlers: dict[int, Any] = {}

    self._register_signal_handler(signal.SIGTERM, SigTermEvent, shutdown=True)
    self._register_signal_handler(signal.SIGINT, SigIntEvent, shutdown=True)
    if hasattr(signal, "SIGHUP"):
        self._register_signal_handler(signal.SIGHUP, SigHupEvent, shutdown=False)
    if hasattr(signal, "SIGTSTP"):
        self._register_signal_handler(signal.SIGTSTP, SigTStpEvent, shutdown=False)
    if hasattr(signal, "SIGCONT"):
        self._register_signal_handler(signal.SIGCONT, SigContEvent, shutdown=False)

Proposed fix:

def _register_shutdown_handlers(self) -> None:
    """Register handlers for graceful shutdown on process exit and signals."""
    atexit.register(self._shutdown)

    self._original_handlers: dict[int, Any] = {}

    # Signal handlers can only be registered from the main thread
    if threading.current_thread() is not threading.main_thread():
        logger.warning(
            "CrewAI telemetry: Skipping signal handler registration (not running in main thread). "
            "To disable this warning or disable crewai telemetry entirely, set CREWAI_DISABLE_TELEMETRY=true. "
            "See: https://docs.crewai.com/telemetry"
        )
        return

    self._register_signal_handler(signal.SIGTERM, SigTermEvent, shutdown=True)
    self._register_signal_handler(signal.SIGINT, SigIntEvent, shutdown=True)
    if hasattr(signal, "SIGHUP"):
        self._register_signal_handler(signal.SIGHUP, SigHupEvent, shutdown=False)
    if hasattr(signal, "SIGTSTP"):
        self._register_signal_handler(signal.SIGTSTP, SigTStpEvent, shutdown=False)
    if hasattr(signal, "SIGCONT"):
        self._register_signal_handler(signal.SIGCONT, SigContEvent, shutdown=False)

Additional context

Operating System: MacOS 15.7.3 (Sequoia)

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