Summary
DDTrace 1.17.0 introduces a regression that breaks php artisan tinker in Laravel applications running in Kubernetes environments. 1.15.2 works correctly; 1.17.0 does not.
Symptom
Running artisan tinker immediately throws:
RuntimeException
Error waiting for execution loop: file_get_contents(.env): Failed to open stream: No such file or directory
Environment
- PHP: 8.3.14
- Laravel: 12.x
- PsySH: via
laravel/tinker
- OS: Alpine Linux 3.19 (Kubernetes pod)
- DDTrace broken:
1.17.0
- DDTrace working:
1.15.2 (and 1.13.0)
Root Cause Analysis
PsySH's ProcessForker (vendor/psy/psysh/src/ExecutionLoop/ProcessForker.php) forks via pcntl_fork() and the parent process waits on a Unix socket pair using @stream_select(). If stream_select() returns false, PsySH reads error_get_last() and throws:
throw new \RuntimeException('Error waiting for execution loop: ' . $err['message']);
In Kubernetes environments, there is no .env file — all config is injected via environment variables. Laravel's bootstrap calls vlucas/phpdotenv, which attempts @file_get_contents('/var/www/html/.env'). The @ suppresses the error display but still sets error_get_last() to:
file_get_contents(/var/www/html/.env): Failed to open stream: No such file or directory
This has always happened at bootstrap, but PsySH's execution loop only surfaces it when stream_select() returns false. With DDTrace 1.15.2, stream_select() succeeds normally. With 1.17.0, it returns false (likely due to a hook into PHP's socket/stream or pcntl internals), causing the stale error_get_last() value to bubble up as the exception message.
Reproduction
- Run a Laravel 12 app in a Kubernetes pod (no
.env file; config from env vars)
- Install DDTrace
1.17.0 via datadog-setup.php
- Run
php artisan tinker
- Observe
RuntimeException: Error waiting for execution loop: file_get_contents(.env): ...
Downgrade to 1.15.2 — issue disappears.
Workaround
Pin DDTrace to 1.15.2 in your Dockerfile:
RUN php -r "readfile('https://github.com/DataDog/dd-trace-php/releases/download/1.15.2/datadog-setup.php');" | php -- --php-bin=all --enable-profiling
Summary
DDTrace
1.17.0introduces a regression that breaksphp artisan tinkerin Laravel applications running in Kubernetes environments.1.15.2works correctly;1.17.0does not.Symptom
Running
artisan tinkerimmediately throws:Environment
laravel/tinker1.17.01.15.2(and1.13.0)Root Cause Analysis
PsySH's
ProcessForker(vendor/psy/psysh/src/ExecutionLoop/ProcessForker.php) forks viapcntl_fork()and the parent process waits on a Unix socket pair using@stream_select(). Ifstream_select()returnsfalse, PsySH readserror_get_last()and throws:In Kubernetes environments, there is no
.envfile — all config is injected via environment variables. Laravel's bootstrap callsvlucas/phpdotenv, which attempts@file_get_contents('/var/www/html/.env'). The@suppresses the error display but still setserror_get_last()to:This has always happened at bootstrap, but PsySH's execution loop only surfaces it when
stream_select()returnsfalse. With DDTrace1.15.2,stream_select()succeeds normally. With1.17.0, it returnsfalse(likely due to a hook into PHP's socket/stream orpcntlinternals), causing the staleerror_get_last()value to bubble up as the exception message.Reproduction
.envfile; config from env vars)1.17.0viadatadog-setup.phpphp artisan tinkerRuntimeException: Error waiting for execution loop: file_get_contents(.env): ...Downgrade to
1.15.2— issue disappears.Workaround
Pin DDTrace to
1.15.2in your Dockerfile: