12 days ago
Detached volumes can't be deleted — CLI and API both report success, neither takes effect
Plan: Hobby · Region: US East · CLI: 5.35.0 (also reproduced on 5.31.0, and directly against the GraphQL API, so it isn't CLI-version-specific)
Summary
A volume with no service attached appears to be unreachable by every interface that could delete it:
- It doesn't render in the dashboard — the UI draws volumes on their service's card, and a detached volume has no card to appear on.
railway volume deleteprintsVolume "<name>" deleted, and the volume is still there afterwards.- The GraphQL mutation
volumeDelete(volumeId:)returns{"volumeDelete": true}, and the volume is still there afterwards.
So it's invisible in the UI, unaffected by the CLI and the API, and still billed. I haven't found a supported way to remove it.
How it happened
I migrated a Postgres service to a different region and deleted the old service afterwards. Deleting the service detached its volume instead of removing it, leaving a volume whose volumeInstance has serviceId = null and state = READY.
I suspect anyone who migrates a database service ends up with one of these.
Reproduction
- Create a service with a volume.
- Delete the service. The volume survives, detached.
railway volume listshows it asAttached to: N/A. The dashboard doesn't show it at all.railway volume delete --volume <id> --yes→ printsVolume "<name>" deleted.railway volume list→ still present. Same result querying the API directly.
What I tried
| Attempt | Reported | Actual |
| --- | --- | --- |
| railway volume delete while detached (CLI 5.31 and 5.35) | Volume "<name>" deleted | still present |
| GraphQL mutation { volumeDelete(volumeId: "…") } | {"volumeDelete": true} | still present |
| Attach it to a new service, then railway volume delete | Volume "<name>" deleted | still present |
| Attach it to a new service, then delete that service via CLI | service removed | volume detached again, survived |
| Attach it to a new service, then delete that service via the dashboard | service removed | volume detached again, survived |
Each attempt was verified with both railway volume list and a direct GraphQL query of project.volumes. The volume id never changed.
Underlying state
Querying project.volumes { volumeInstances { serviceId state } }:
orphaned volume volumeInstances = [ { serviceId: null, state: READY } ]
healthy volume volumeInstances = [ { serviceId: "<svc-id>", state: READY } ]The detached volume keeps a volumeInstance with a null serviceId. Schema introspection shows no volumeInstanceDelete mutation, so there's no way to remove that instance — which I'd guess is what stops volumeDelete from completing.
Expected
Either volumeDelete removes a detached volume, or it returns an error saying why it can't — rather than reporting success while the volume persists and keeps billing.
Two smaller things in the same area
- Deleting a service silently orphans its volume. If that's intentional, the volume should stay visible somewhere in the UI afterwards, otherwise it becomes unreachable the moment the service is gone.
- The success message is wrong.
Volume "<name>" deletedandvolumeDelete: trueon a no-op is what made this slow to diagnose — the natural read is caching or propagation lag, not failure, so you keep waiting for something that's never going to happen.
Impact
Small in absolute terms — the volume is ~116 MB, about $0.02/month. But it can't be removed or even seen, and it seems like a predictable side effect of a routine database migration.
Happy to share the project, volume and service ids privately if that's useful for reproducing.
2 Replies
12 days ago
The delete did take effect. Volumes that still hold data enter a 48-hour retention window before permanent removal (a safety measure against accidental data loss), so the volume remains visible in queries during that period even though it is already queued for deletion. The detached postgres volume in your project is currently in that window and will be permanently removed once it elapses. A restoration link was emailed to you when the deletion was queued, in case you need to cancel it.
Status changed to Awaiting User Response Railway • 12 days ago
Railway
The delete did take effect. Volumes that still hold data enter a 48-hour retention window before permanent removal (a safety measure against accidental data loss), so the volume remains visible in queries during that period even though it is already queued for deletion. The detached postgres volume in your project is currently in that window and will be permanently removed once it elapses. A restoration link was emailed to you when the deletion was queued, in case you need to cancel it.
12 days ago
Thanks — that explains it completely, and my report was wrong on the main point. The deletes did work; I read the volume still appearing in volume list and in the API as evidence they hadn't, and kept re-running them against something already queued.
Two smaller things from the same episode, offered as feedback rather than bug reports:
The success message doesn't mention the retention window. Volume "<name>" deleted and volumeDelete: true are both accurate, but with the volume still present afterwards the natural read is "the call no-opped" rather than "it's queued and retained for 48 hours." Something like queued for deletion — retained for 48h would have ended my investigation at the first attempt instead of the fifth.
Detached volumes don't appear in the dashboard. Since the UI renders volumes on their service's card, a volume with no service has nowhere to show up. That's what sent me to the CLI and API in the first place, and it means there's no UI path to see or cancel a pending deletion for exactly the volumes most likely to have one — the retention window and restoration email are doing real work that's invisible unless you know to look for the email.
Neither is urgent. Appreciate the quick and clear answer.
Status changed to Awaiting Railway Response Railway • 12 days ago
Status changed to Solved meirelon • 12 days ago