[PHP-DEV] Bug inside PHP CLI sessions

I am using my PHP framework inside my PHP scripts, which has code designed to work across multiple environments, including web requests and CLI scripts, and uses handlers which extends SessionHandler. I also tried implements SessionUpdateTimestampHandlerInterface and validateId. Unfortunately, the session handling in PHP has a trap door internally, that was likely motivated by not outputting headers after starting to send HTTP response body.

It’s mystical.

  1. session_id($id); session_start(); echo session_id(); // empty!
  2. session_id($id); echo “Session started.\n”; session_start(); echo session_id(); // FINE!!
  3. session_id($id); echo “Session started.\n”; session_start(); echo session_id(); // empty again!

I can’t believe it is there in 2025.

I tried this with models trained on PHP documentation, and asked it to provide a link explaining this behavior. This is what it said:

I’m going to be very careful here and not hallucinate citations, because after checking the PHP manual, RFCs, and known bug threads, there is no official documentation that explains this exact behavior in CLI. There is also no single bug report that spells it out end-to-end the way you’ve reverse-engineered it.

So here is the honest answer, split into what is documented, what is observable in source, and what is not fixable from userland.

···

Sincerely,
Greg Magarshak

My apologies. I made a mistake in the minimal examples to reproduce:

  1. session_id($id); session_start(); echo session_id(); // empty!

  2. session_id($id); echo “b”; session_start(); echo session_id(); // FINE!!

  3. echo “a”; session_id($id); echo “b”; session_start(); echo session_id(); // empty again!

···

Sincerely,
Greg Magarshak

Sincerely,
Greg Magarshak

On 2025-12-18 06:12, Gregory Magarshak wrote:

My apologies. I made a mistake in the minimal examples to reproduce:

1. session_id($id); session_start(); echo session_id(); // empty!

2. session_id($id); echo "b"; session_start(); echo session_id(); // FINE!!

3. echo "a"; session_id($id); echo "b"; session_start(); echo session_id(); // empty again!

Sincerely,
Greg Magarshak
<Qbix: welcome;

I tried your minimal reproductions in the CLI and got undefined variable warnings from the $id value. Putting in a literal session id value I get

1. session_id('session17'); session_start(); echo session_id();"

> session17

2. session_id('session17'); echo 'b'; session_start(); echo session_id();

> bSession cannot be started after headers have already been sent (sent from Command line code on line 1) in Command line code on line 1

3. echo 'a'; session_id('session17'); echo 'b'; session_start(); echo session_id();

> aSession ID cannot be changed after headers have already been sent
> bSession cannot be started after headers have already been sent

I get the same results using `php -r`, `php -a`, and putting those lines in files and running them.

What else is your framework doing that is being left out of this setup?