How to fix the "array to string conversion" error in coolify docker compose
How to fix the "array to string conversion" error in coolify docker compose
How to fix the "array to string conversion" error in coolify docker compose deployments
If you have ever attempted to import a perfectly-valid docker-compose.yml into Coolify (or another PHP-based tool such as Portainer, Shipyard, Rancher 1.x) and been greeted by the notice above, you have already discovered an odd corner where Docker Compose ≠ YAML ≠ PHP array handling.
In this post we will:
- Reproduce the problem with a minimal snippet
- Walk through five common trouble spots
- Show the before → after diff that cures the warning
- Explain why older PHP Compose parsers choke and what to do if you cannot change the file format
The smoking gun
Here's a minimal example that triggers the error:
Feed that file into Coolify 4.0-beta 419 and the container never starts; the logs show:
Compose itself (docker compose config) is perfectly happy.
The problem lies in Coolify's vintage Compose-to-PHP converter, which was written for the v2 spec (2017) where many fields were always scalars.
1 — Extended depends_on objects → simple string list
🔴 Problem
The PHP helper tries to implode() that object.
✅ Fix
Loss of behaviour?
None for most setups: Coolify doesn't wait on health-checks anyway.
If you need the conditional version, keep your object form but upgrade to Coolify ≥ 4.1 where the new Go parser has landed.
2 — Long-form ports, volumes, networks → short strings
🔴 Problem
✅ Fix
Same pattern for volumes and service-scoped networks:
3 — Array-form command / healthcheck.test → folded scalars
🔴 Problem
✅ Fix
Why it works: the Symfony YAML component inside Coolify converts a folded block scalar into a PHP string – the type the next layer expects.
4 — Empty mapping stubs → delete them
YAML treats {} as an empty map, which becomes array() in PHP.
If a later helper concatenates that value you hit the notice.
🔴 Problem
✅ Fix
Just remove the key entirely:
Same for unused top-level sections:
5 — Explicit external networks & restart policies
Older Coolify releases implicitly converted unknown networks to strings, so make external intent clear:
One-shot jobs (migration, setup_config) must not inherit restart: always from copy-paste.
Use the spec value:
Putting it all together
Below is a fully-working Compose file for our Hatchet stack after applying every fix. You can drop it into Coolify ≤ 4.0 and the PHP warning disappears:
Why does PHP trip but Docker doesn't?
- Docker uses docker/compose-go (Go structs)
- Coolify ≤ 4.0 used Symfony YAML → PHP arrays → DTOs
- The legacy DTOs expect scalar strings in many places; when Symfony hands them an array they fall back to
__toString()which produces the notice - Upgrading to Coolify 4.1+ (or any tool that embeds the official compose-spec library) fixes the root cause
- Until you can, the five edits above are a reliable workaround
TL;DR / Cheatsheet
| Culprit | Bad example | Good example |
|---|---|---|
| Extended depends_on | object | list |
| Long-form ports/volumes | mapping | "host:container" |
| List-form command | array | folded scalar |
| Empty maps | (delete) | |
| Implicit network / wrong restart | missing / default | external: true / "no" |
You can likely paste this into an LLM along with your docker-compose.yml and it will fix it for you.