Skip to content

fix(log): avoid Array to string conversion warning in SimpleFormatter#8

Merged
ralflang merged 3 commits into
FRAMEWORK_6_0from
fix/simpleformatter-array-context
Jul 11, 2026
Merged

fix(log): avoid Array to string conversion warning in SimpleFormatter#8
ralflang merged 3 commits into
FRAMEWORK_6_0from
fix/simpleformatter-array-context

Conversation

@TDannhauer

Copy link
Copy Markdown
Contributor

Summary

  • Fix a PHP "Array to string conversion" warning in SimpleFormatter::format() when a log context value is an array or object.

Motivation

Reported while investigating horde/imp#88: a log entry with array context data triggered this warning, which — depending on the configured error handler — can swallow or corrupt the very log entry being written. That made it hard to get reliable diagnostics out of horde.log for that issue.

Changes

  • SimpleFormatter::format() now JSON-encodes array/object context values before interpolating them into the format string, instead of relying on implicit (string) casting.
  • Added a regression test covering array context values.

Test plan

  • vendor/bin/phpunit test/Formatter/SimpleFormatterTest.php (18/18 passing)

Context values that are arrays or objects (e.g. extra fields passed
through Horde::log()) triggered a PHP "Array to string conversion"
warning when interpolated into the format string, which could mask
or corrupt the intended log entry. Encode non-scalar values as JSON
before interpolation instead.
@TDannhauer TDannhauer requested a review from ralflang July 8, 2026 20:57

@ralflang ralflang left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. Which context exactly got provided as structured data? Usually these fields are not supposed to be logged this way.

@TDannhauer

Copy link
Copy Markdown
Contributor Author

Fair question — here is the concrete evidence and why I think the formatter needs the guard.

Where this was observed

Not constructed by me — it comes from a user's production log on a stock install (horde 6.0.0 / core 3.1.0 / imp 7.0.x), reported in horde/imp#88: horde/imp#88 (comment)

HORDE 2026-07-06T06:52:32-07:00 warning: [horde] PHP ERROR: Array to string conversion [pid 18119 on line 85 of "/var/www/horde/vendor/horde/log/src/Formatter/SimpleFormatter.php"]

Line 85 is the str_replace("%$name%", (string) $value, $output) in format().

Why "these fields are not supposed to be logged this way" doesn't prevent the warning

Agreed — structured context is not supposed to end up in the format string. But format() casts every context value with (string), including values whose %name% placeholder does not occur in the format string at all. With the default format %timestamp% %levelName%: %message%, any log call that carries an array anywhere in its context triggers the warning, even though that field was never going to be printed. So the warning does not indicate that someone tried to print an array — it fires for context that was correctly not referenced in the template.

Why array context is legitimate input

  • PSR-3: context "can contain anything", and "implementors MUST ensure they treat context data with as much lenience as possible".
  • This package's own compliance test enforces exactly that: Psr3ExceptionKeyComplianceTest::testContextLeniencyWithInvalidException() logs ['exception' => ['array' => 'value']] and asserts it is accepted. Attach a SimpleFormatter to that handler and the accepted input emits a PHP warning.
  • Psr3Formatter::format() in this package already guards for this case ("Filter out incompatible objects, arrays etc"). SimpleFormatter is the only formatter in the default chain without such a guard — and Horde\Core\Factory\LogHandlerFactory stacks exactly Psr3Formatter + SimpleFormatter for the default file handler, so every stock Horde 6 install routes all log context through this code path.

Why it matters in practice

The warning fires while a log line is being formatted. Depending on the error handler, that warning is fed back through the same logging pipeline and can suppress or garble the entry being written. In imp#88 that degraded the diagnostics we were trying to collect.

Open to an alternative

If you would rather have non-scalar values never appear in output at all, I am happy to change the patch to skip them the way Psr3Formatter does (or to only substitute placeholders actually present in the format string, which also avoids the cast). I chose JSON encoding so that a template that does reference such a field still shows something useful — but skipping is equally fine. Your call.

@TDannhauer TDannhauer requested a review from ralflang July 10, 2026 11:23
@ralflang ralflang merged commit ecb9e10 into FRAMEWORK_6_0 Jul 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants