Skip to content

Regression in 1.17.0: artisan tinker fails with RuntimeException from PsySH stream_select() in Laravel/K8s environments #3727

@jwadhams

Description

@jwadhams

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

  1. Run a Laravel 12 app in a Kubernetes pod (no .env file; config from env vars)
  2. Install DDTrace 1.17.0 via datadog-setup.php
  3. Run php artisan tinker
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions