The multi-destination 400 is unactionable, and arrives after apply has already mutated Coolify #41
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:apply
scope:capture
scope:coolify-api
scope:fleet
scope:manifest
scope:secrets
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/cast#41
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happens
A first apply against a server with more than one destination gets this, from Coolify, on the first resource create:
By then cast has already created the project and the environment. The run is half-applied, and the message names neither the fix nor the file it goes in.
Why cast cannot pre-flight it (and what it can do instead)
Coolify 4.1.2 serves no destinations API — not list, not read, not create.
GET /servers/{uuid}does not expose them either (theServerschema has no destination field). So cast genuinely cannot know a server's destination count before attempting a create. That is not fixable here.What is fixable is the diagnosis. Two things:
1. Translate the 400. Catch this specific Coolify message and re-raise it as something that names the remedy:
2. Make the assumption visible in the plan. Today an undeclared
destination_uuidis silent, and cast's own source calls it "the server's only destination, which is what Coolify picks anyway". That inference is invisible until it is wrong. When nodestination_uuidis declared, the plan should say so out loud — one line, e.g.placement: server's default destination (none declared)— so the assumption is on screen at the moment it is being made rather than in a comment.Why this bites harder than a normal 400
Placement is create-time: apply never moves a resource between networks, so recovering from a wrong or missing destination means delete + recreate. And the failure mode is asymmetric in a way that hides itself — a single-destination server ignores
destination_uuidentirely and never validates it (so a wrong value is invisible), while a multi-destination server hard-400s any create that omits it. The moment a server gains its second destination, every project on it that never declared one stops being able to deploy.