Skip to content

Worker crashes are logged at debug level only: invisible in production, in-flight request becomes an empty 500 #2601

Description

@luminalpark

What happened?

A worker script that dies after boot with a non-zero exit status (StopReasonCrash) logs the same debug-level "restarting" message as a clean FRANKENPHP_LOOP_MAX recycle — same level, same message text (threadworker.go, tearDownWorkerScript). At the default log level a crash is therefore invisible to operators:

  • the in-flight request surfaces as an empty 500 (0 bytes emitted after normal processing time — we also observed one response truncated mid-stream),
  • the application never gets to log anything, since the script died mid-request,
  • and exit_status — the one datum needed to triage the death — is only obtainable by running the whole server at debug level.
    What we expected: a worker crash that takes a user request down with it to be visible at the default log level, as it was up to v1.2.x, where this exact case was logged at error level with a distinct message (worker.go @ v1.2.5):
if c := l.Check(zapcore.ErrorLevel, "unexpected termination, restarting"); c != nil {
    c.Write(zap.String("worker", absFileName), zap.Int("exit_status", int(fc.exitStatus)))
}

That error-level line is, for instance, how the reporter of #774 noticed their problem at all. Somewhere in the worker-thread refactoring both paths converged on debug-level "restarting".
How we hit it: production e-commerce (Shopware 6.7 on the Symfony runtime, 4 workers, num_threads 6 / max_threads 12). frankenphp_worker_crashes increments steadily at ~0.02–0.03% of worker requests (e.g. 12 crashes over 54,957 worker requests on one container, 19 over ~54,000 on its twin), each increment pairing with one empty-500 in the access log within the same 2-minute sampling window. Nothing in the app log, nothing on stderr (zero Fatal error / Allowed memory size lines), nothing from FrankenPHP at the default level. It took us three debugging sessions to find the Prometheus counter, and we still do not know our workers' exit statuses.
Steps to reproduce the logging behavior (not our production crash — that one we cannot minimize): a worker script that boots fine and calls exit(1) while handling a request. The in-flight request returns an empty 500 and the only log line is level=DEBUG msg=restarting ... exit_status=1.
Two side questions while we are here:

  1. Are the metric semantics documented anywhere? From the source: worker_crashes = non-zero exit after boot; worker_restarts = clean exits, which includes FRANKENPHP_LOOP_MAX recycling. Our numbers suggest downscaled worker threads also count as restarts — is that intended?
  2. Is the empty 500 the intended response for the request in flight when the worker dies? A 502 would let proxies/caches distinguish "backend script died" from application-level 500s.
    To be explicit: we are not claiming the crashes themselves are FrankenPHP's fault — the cause may well be in our application or an extension. The issue is that the current logging makes it nearly impossible for an operator to find out.
    We have a small PR ready that restores the historical message at warn level (keeping clean restarts at debug) and adds a regression test — will link it here.

Build Type

Docker (Debian Trixie)

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

phpinfo() output
# php -i output; Environment and PHP Variables sections omitted, internal hostnames/DSN redacted
phpinfo()
PHP Version => 8.5.7
System => Linux f86a1845f733 6.17.0-1018-azure #18~24.04.1-Ubuntu SMP Thu May 28 16:39:11 UTC 2026 x86_64
Build Date => Jun 11 2026 00:26:07
Build System => Linux - Docker
Build Provider => https://github.com/docker-library/php
Configure Command =>  './configure'  '--build=x86_64-linux-gnu' '--sysconfdir=/usr/local/etc' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--with-mhash' '--with-pic' '--enable-mbstring' '--enable-mysqlnd' '--with-password-argon2' '--with-sodium=shared' '--with-pdo-sqlite=/usr' '--with-sqlite3=/usr' '--with-curl' '--with-iconv' '--with-openssl' '--with-readline' '--with-zlib' '--enable-phpdbg' '--enable-phpdbg-readline' '--with-pear' '--with-libdir=lib/x86_64-linux-gnu' '--enable-embed' '--enable-zts' '--disable-zend-signals' 'build_alias=x86_64-linux-gnu' 'PHP_UNAME=Linux - Docker' 'PHP_BUILD_PROVIDER=https://github.com/docker-library/php'
Server API => Command Line Interface
Virtual Directory Support => enabled
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => (none)
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-amqp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-apcu.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bcmath.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bz2.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ffi.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ftp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gmp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-redis.ini,
/usr/local/etc/php/conf.d/docker-php-ext-soap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sockets.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zstd.ini,
/usr/local/etc/php/conf.d/docker.ini
PHP API => 20250925
PHP Extension => 20250925
Zend Extension => 420250925
Zend Extension Build => API420250925,TS
PHP Extension Build => API20250925,TS
PHP Integer Size => 64 bits
Debug Build => no
Thread Safety => enabled
Thread API => POSIX Threads
Zend Signal Handling => disabled
Zend Memory Manager => enabled
Zend Multibyte Support => provided by mbstring
Zend Max Execution Timers => enabled
IPv6 Support => enabled
DTrace Support => disabled
Registered PHP Streams => https, ftps, compress.zlib, php, file, glob, data, http, ftp, compress.bzip2, phar, zip, compress.zstd
Registered Stream Socket Transports => tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2, tlsv1.3
Registered Stream Filters => zlib.*, convert.iconv.*, string.rot13, string.toupper, string.tolower, convert.*, consumed, dechunk, bzip2.*
This program makes use of the Zend Scripting Language Engine:
Zend Engine v4.5.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.7, Copyright (c), by Zend Technologies
 _______________________________________________________________________
Configuration
amqp
Version => 2.2.0dev
Compiled => Jun 13 2026 @ 05:47:34
AMQP protocol version => 0-9-1
librabbitmq version => 0.15.0
Default max channels per connection => 256
Default max frame size => 131072
Default heartbeats interval => 0
Directive => Local Value => Master Value
amqp.auto_ack => 0 => 0
amqp.cacert => no value => no value
amqp.cert => no value => no value
amqp.channel_max => 256 => 256
amqp.connect_timeout => 0 => 0
amqp.deserialization_depth => 128 => 128
amqp.frame_max => 131072 => 131072
amqp.global_prefetch_count => 0 => 0
amqp.global_prefetch_size => 0 => 0
amqp.heartbeat => 0 => 0
amqp.host => localhost => localhost
amqp.key => no value => no value
amqp.login => guest => guest
amqp.password => guest => guest
amqp.port => 5672 => 5672
amqp.prefetch_count => 3 => 3
amqp.prefetch_size => 0 => 0
amqp.read_timeout => 0 => 0
amqp.rpc_timeout => 0 => 0
amqp.sasl_method => AMQP_SASL_METHOD_PLAIN => AMQP_SASL_METHOD_PLAIN
amqp.serialization_depth => 128 => 128
amqp.timeout => no value => no value
amqp.verify => 1 => 1
amqp.vhost => / => /
amqp.write_timeout => 0 => 0
apcu
APCu Support => Disabled
Version => 5.1.28
APCu Debugging => Disabled
MMAP Support => Enabled
MMAP File Mask =>  
Serialization Support => Disabled
Build Date => Jun 13 2026 05:45:21
Directive => Local Value => Master Value
apc.coredump_unmap => Off => Off
apc.enable_cli => Off => Off
apc.enabled => On => On
apc.entries_hint => 0 => 0
apc.gc_ttl => 3600 => 3600
apc.mmap_file_mask => no value => no value
apc.mmap_hugepage_size => 0 => 0
apc.preload_path => no value => no value
apc.serializer => php => php
apc.shm_size => 32M => 32M
apc.slam_defense => Off => Off
apc.smart => 0 => 0
apc.ttl => 0 => 0
apc.use_request_time => Off => Off
bcmath
BCMath support => enabled
Directive => Local Value => Master Value
bcmath.scale => 0 => 0
bz2
BZip2 Support => Enabled
Stream Wrapper support => compress.bzip2://
Stream Filter support => bzip2.decompress, bzip2.compress
BZip2 Version => 1.0.8, 13-Jul-2019
Core
PHP Version => 8.5.7
Directive => Local Value => Master Value
allow_url_fopen => On => On
allow_url_include => Off => Off
arg_separator.input => & => &
arg_separator.output => & => &
auto_append_file => no value => no value
auto_globals_jit => On => On
auto_prepend_file => no value => no value
browscap => no value => no value
default_charset => UTF-8 => UTF-8
default_mimetype => text/html => text/html
disable_functions => no value => no value
display_errors => Off => Off
display_startup_errors => Off => Off
doc_root => no value => no value
docref_ext => no value => no value
docref_root => no value => no value
enable_dl => On => On
enable_post_data_reading => On => On
error_append_string => no value => no value
error_log => no value => no value
error_log_mode => 0644 => 0644
error_prepend_string => no value => no value
error_reporting => E_ALL => E_ALL
expose_php => Off => Off
extension_dir => /usr/local/lib/php/extensions/no-debug-zts-20250925 => /usr/local/lib/php/extensions/no-debug-zts-20250925
fatal_error_backtraces => On => On
fiber.stack_size => no value => no value
file_uploads => On => On
hard_timeout => 2 => 2
highlight.comment => <span style="color: #FF8000">#FF8000</span> => <span style="color: #FF8000">#FF8000</span>
highlight.default => <span style="color: #0000BB">#0000BB</span> => <span style="color: #0000BB">#0000BB</span>
highlight.html => <span style="color: #000000">#000000</span> => <span style="color: #000000">#000000</span>
highlight.keyword => <span style="color: #007700">#007700</span> => <span style="color: #007700">#007700</span>
highlight.string => <span style="color: #DD0000">#DD0000</span> => <span style="color: #DD0000">#DD0000</span>
html_errors => Off => Off
ignore_repeated_errors => Off => Off
ignore_repeated_source => Off => Off
ignore_user_abort => Off => Off
implicit_flush => On => On
include_path => .:/usr/local/lib/php => .:/usr/local/lib/php
input_encoding => no value => no value
internal_encoding => no value => no value
log_errors => Off => Off
mail.add_x_header => Off => Off
mail.cr_lf_mode => crlf => crlf
mail.force_extra_parameters => no value => no value
mail.log => no value => no value
mail.mixed_lf_and_crlf => Off => Off
max_execution_time => 0 => 0
max_file_uploads => 20 => 20
max_input_nesting_level => 64 => 64
max_input_time => -1 => -1
max_input_vars => 1000 => 1000
max_memory_limit => -1 => -1
max_multipart_body_parts => -1 => -1

Relevant log output

Relevant log output
# Example of the empty 500 in the Caddy access log (abridged, hostnames redacted).
# Note duration: normal render-time band (successful requests average ~0.18s) — not a timeout.
{"level":"error","logger":"http.log.access","msg":"handled request","request":{"method":"GET","host":"<redacted-host>","uri":"/de-de/kaeuferschutz/datenschutz/"},"duration":0.215,"size":0,"status":500}

# Metrics from the same container at that time:
frankenphp_worker_crashes{worker="/var/www/html/public/index.php"} 12
frankenphp_worker_restarts{worker="/var/www/html/public/index.php"} 178
frankenphp_worker_request_count{worker="/var/www/html/public/index.php"} 54957

# There is NO frankenphp log line accompanying these 12 crashes at the default
# log level — which is precisely this issue. App error log and stderr are empty
# for these requests as well.

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