21 hours ago
We are checking two production services using Railway's GraphQL API. The same read-only deployment/source/repoTrigger query returned HTTP 200 with data:null and errors present during separate observation windows on October 10, 2026:
- 22:40:20.448543 UTC: error count was not retained.
- 23:10:26.746766 UTC: exactly one error was recorded.
- 23:40:26.818628 UTC: exactly one error was recorded.
Responses had complete bounded bodies and parsed as JSON. Our strict release verification rejects the result. Earlier authenticated dashboard observations showed both services online and successful matching deployments. We have not established an end-customer outage. This problem blocks verification for our next release.
Could you help determine whether this selection is affected by a field-specific authorization restriction or a platform issue, and which existing-access check distinguishes those cases? Our fixed diagnostic maps a recognized error code to TRANSIENT, but that label does not establish its cause. Raw error messages and a traceId were not retained in our approved safe projection.
The query structure is below. Resource identifiers and authorization headers are omitted; no variable values are included.
query CandidateProviders($front:String!,$back:String!,$environmentId:String!){ frontend:serviceInstance(serviceId:$front,environmentId:$environmentId){latestDeployment{id projectId environmentId serviceId status deploymentStopped meta}activeDeployments{id status deploymentStopped meta}rootDirectory source{repo image}service{projectId repoTriggers{edges{node{projectId environmentId serviceId branch checkSuites repository}}}}} backend:serviceInstance(serviceId:$back,environmentId:$environmentId){latestDeployment{id projectId environmentId serviceId status deploymentStopped meta}activeDeployments{id status deploymentStopped meta}rootDirectory source{repo image}service{projectId repoTriggers{edges{node{projectId environmentId serviceId branch checkSuites repository}}}}}}3 Replies
21 hours ago
An HTTP 200 with errors present doesn't tell you the cause by itself. Our authorization refusals also come back as HTTP 200, and their extensions.code reads INTERNAL_SERVER_ERROR because that is the default code for an error that doesn't set its own. So a recognized error code mapped to TRANSIENT can't tell an authorization refusal apart from a server-side fault.
The details that do tell them apart are the error's message and path, which your safe projection currently drops. The path shows which field in the selection failed. To check which existing access the token has, send query { apiToken { workspaces { id name } } } with the same Bearer token. That returns the workspace or workspaces the token can reach, so you can confirm both services sit inside that scope. For a project token, send query { projectToken { projectId environmentId } } with the Project-Access-Token header instead.
Status changed to Awaiting User Response Railway • about 21 hours ago
20 hours ago
A further unchanged request returned HTTP 200, one error path at the backend alias, and matched the exact documented authorization-denial wording. Our strict acceptance check remains blocked. What non-mutating existing-access check can identify why that field is denied?
Status changed to Awaiting Railway Response Railway • about 20 hours ago
an hour ago
None of the fields in that selection have their own authorization rule. latestDeployment, activeDeployments, rootDirectory, source, and service.repoTriggers (including checkSuites and repository) are readable at the same viewer-level access as the service instance itself, for both project and workspace tokens. So a "Not Authorized" error whose path stops at the backend alias, while frontend resolves, means the token cannot reach that service instance at all. It is not a denial of one sub-field.
To check this without changing anything, send query { backend: serviceInstance(serviceId: $back, environmentId: $environmentId) { id } } with the same token. If that minimal query is also denied, the problem is access to that serviceId and environmentId pair, not your field selection. Then compare that pair against the token's scope. Use query { apiToken { workspaces { id name } } } for an account or workspace token, or query { projectToken { projectId environmentId } } for a project token, since project tokens are limited to one environment. With user credentials, projectMembers(projectId: ...) { role } shows the role on that project.
Status changed to Awaiting User Response sam-a • about 1 hour ago