2 days ago
Hi Railway team,
I'm hitting a routing inconsistency where a custom domain on a healthy, deployed service returns 400 "Invalid Hostname" from Railway's edge — and the same error appears when accessing the service-pattern *.up.railway.app URL directly. Our production project with the same setup pattern works fine, so I think there's a stale or misconfigured routing entry on Railway's side that we can't fix from the UI.
Setup:
Staging project (separate Railway project from our working production project)
Service:
happy-grace— a .NET 10 web API listening on port 8080Region: EU West
Deployment status: Active, 1 replica, last successful deploy at 2026-05-11 16:40 CEST
Application logs show a clean boot: EF Core migrations applied, listening on
http://+:8080, retention job ran, no errors Custom domain added to the service: xxx.comCloudflare DNS records (values taken directly from Railway's "Configure DNS Records" dialog):
CNAME api-staging → 4o9vn8ki.up.railway.app(Proxied)TXT _railway-verify.api-staging → railway-verify=48da151544422553b953a7187ee5dc1…(DNS only)
Railway UI shows TXT ✓ verified, CNAME
. Our production project also shows
on its CNAME yet routes fine, so I'm not treating the icon as the cause.
Symptoms (all measured 2026-05-11 18:02 CEST):
Custom domain via Cloudflare:
$ curl -i https://xxx/api/v1/healthHTTP/2 400
server: cloudflare
x-railway-edge: railway/europe-west4-drams3a
x-railway-request-id: i8hEfy38T-miYEham3z_FQ
→ "Bad Request - Invalid Hostname"
Service-pattern URL hitting Railway edge directly (no Cloudflare in between):
$ curl -i https://happy-grace-staging.up.railway.app/api/v1/healthHTTP/2 400
server: railway-edge
x-railway-edge: railway/europe-west4-drams3a
x-railway-request-id: 6TnevfpER2OZXnvFw9P4nw
→ "Bad Request - Invalid Hostname"
Both responses are clearly from Railway-edge (x-railway-edge header present). Same error body. Different request-id so they're distinct requests, but same routing-table miss.
For reference, two other adjacent hostnames behave differently:
4o9vn8ki.up.railway.app(the CNAME target Railway gave me) returns 404 withx-railway-fallback: true— same asry4dgixo.up.railway.appfor our production service, so I believe this is expected for the verify-anchor URL.happy-grace.up.railway.app(without env suffix) returns the same 404 fallback.
So Railway's edge knows about the two 400-returning hostnames (otherwise it would fall through to the 404 fallback), but resolves them to something invalid.
What I've tried:
Toggled Cloudflare proxy status (Proxied
DNS-only) and waited between toggles — no change.Forced re-deploys of the service after env-var changes (Postgres + Redis connection strings adjusted) — service comes up clean each time, but the routing error stays the same.
Verified the custom domain is attached to the
happy-graceservice, not to Admin / Postgres / Redis.
Our production project (xxx.com → ry4dgixo.up.railway.app, same Cloudflare zone, same proxy settings) works without issue.
Request IDs:
i8hEfy38T-miYEham3z_FQ— custom-domain 4006TnevfpER2OZXnvFw9P4nw— service-pattern URL 400uoA1O343Qpyk-xI7ALIuDA— CNAME-target 404 (for comparison)BYFkMkeJTZ6a1k9PEuroCg— bare service-name 404 (for comparison)tCdcjFgST26kMvKz7fhULg— production CNAME-target 404 (showing the verify-anchor pattern is the same on the working project)
Ask:
Could you check what's bound to the happy-grace-staging.up.railway.app and xxx.com entries in the edge routing tables for our staging project? It looks like Railway has a routing entry registered for those hostnames but pointed at something invalid (otherwise we'd see the 404 fallback instead of the 400). I suspect a remove-and-readd of the custom domain on our side might fix it, but I'd rather understand what's broken first so we don't keep recreating the same broken state.
Happy to share project / deployment / service IDs — let me know what format works best.
Thanks,
Chris
3 Replies
2 days ago
This thread has been marked as public for community involvement, as it does not contain any sensitive or personal information. Any further activity in this thread will be visible to everyone.
Status changed to Open Railway • 2 days ago
2 days ago
I would split the two hostnames here, because they do not prove quite the same thing.
For the Railway-provided hostname: happy-grace-staging.up.railway.app only works if Railway actually generated/registered that exact public domain for the service/environment. I would not infer it from the service + environment names. In the service's Networking/Public Networking panel, use the exact generated *.up.railway.app domain shown there, or click Generate Domain if none exists. A guessed hostname returning Railway edge Invalid Hostname is consistent with "this Host header is not bound to a service," even when the deployment itself is healthy.
For the custom domain: Railway's current domain docs require both records to be present exactly as shown: the CNAME routes traffic and the TXT verifies ownership. The CNAME target itself returning the 404 fallback is normal; it is just the routing/verification target, not necessarily a direct service URL. The custom domain should start routing only when Railway has a verified custom-domain binding for api-staging.led-konfigurator.com.
The two things I would try next:
In Railway, remove and re-add
api-staging.led-konfigurator.comon thehappy-graceservice in the staging environment, then copy the fresh CNAME and TXT values from that dialog. Do not reuse the old target if Railway gives a new one.2. In Cloudflare, make sure there are no A/AAAA/CNAME conflicts for
api-staging, add the TXT exactly, and temporarily set the CNAME to DNS-only while Railway verifies it. Once Railway shows the domain as verified/routing, re-enable the proxy if you want it; for Cloudflare proxy mode, Railway also documents using Full SSL mode rather than Full Strict.
If it still returns 400 after that, then I agree this is likely a stale/misbound Railway edge route. At that point the useful staff payload is: project ID, service ID, environment ID, custom domain ID if visible, the fresh CNAME/TXT values, and the Railway request IDs you already captured i8hEfy38T-miYEham3z_FQ and 6TnevfpER2OZXnvFw9P4nw). That gives Railway enough to inspect the edge routing table directly.
2 days ago
Hi abergelnathan, thanks for the suggestions
Applied per your advice:
Removed and re-added the custom domain on the service in the staging environment
Used the fresh CNAME + TXT values from the new "Configure DNS Records" dialog
Cloudflare DNS: no A/AAAA conflicts, TXT value exact, CNAME set to DNS-only during the verification window
Cloudflare SSL/TLS encryption mode set to Full (not Full Strict)
The custom domain still returns 400 "Invalid Hostname" from Railway-edge.
In parallel, I renamed the service. That produced an additional data point that I think narrows things down:
The previous Railway-generated public domain (the one tied to the old service name) now returns the expected 404 "Application not found" with
x-railway-fallback: true— released after rename, normal behavior.The new Railway-generated public domain
konfigurator-2026-staging-staging.up.railway.app(taken directly from the Networking panel) returns the same 400 "Invalid Hostname":
$ curl -i https://konfigurator-2026-staging-staging.up.railway.app/api/v1/healthHTTP/2 400
server: railway-edge
x-railway-edge: railway/europe-west4-drams3a
→ "Bad Request - Invalid Hostname"
(request-id ends in ...WVMv1w)
So the broken edge-routing entry follows the service identity across renames — the new hostname inherits the same fault as soon as it gets bound. That suggests the broken state is attached to the service/environment record in Railway's edge, not to a specific hostname string.
The custom domain via Cloudflare also still fails the same way (request-id ends in ...N8N_Fg).
Could Railway Team inspect the edge routing table directly for this service and clear/rebuild whatever entry is broken? I'm happy to share the project/service/environment IDs and the full request IDs via DM or any private channel with Railway Team directly.
Thanks!
2 days ago
Thanks for testing that. That result is a strong confirmation that DNS/Cloudflare is no longer the variable: the new Railway-generated domain coming directly from Networking should route without Cloudflare, and if it also returns Railway-edge 400 immediately after being bound, the bad state is almost certainly on the Railway side.
At this point I would stop changing DNS and avoid deleting/recreating more domains, because it may keep attaching the same broken service/environment route. The most useful escalation packet for Railway staff is:
- project ID
- service ID
- environment ID
- the current generated domain
- custom domain ID if visible
- request IDs from both the generated domain and custom domain failures
- note that the old generated domain now falls back to 404, while the new bound generated domain returns 400
The key clue for staff: fallback 404 = hostname unbound; edge 400 on a freshly generated bound hostname = hostname is bound but resolves to an invalid or miswired backend/route entry. That should let them clear/rebuild the edge binding for that service/environment instead of continuing DNS troubleshooting.