Error Handling
GraphQL does not use HTTP status codes for application-level errors. The API always returns HTTP 200 for valid GraphQL requests, even when the operation fails. Errors are communicated through the errors array in the response body.
Understand GraphQL errors
A successful response with no errors looks like this:
{
"data": {
"vm": {
"id": "abc123",
"name": "web-01",
"status": "running"
}
}
}
When something goes wrong, the response includes an errors array alongside (potentially partial) data:
{
"data": {
"vm": null
},
"errors": [
{
"message": "vm not found",
"path": ["vm"],
"extensions": {
"code": "NOT_FOUND"
}
}
]
}
Key fields in each error object:
| Field | Description |
|---|---|
message | Human-readable description of what went wrong. |
path | The field path in the query where the error occurred. |
extensions | Additional metadata, often including an error code. |
data and errors in your client.Handle authorization errors
When you attempt an operation without the required role, the API returns an authorization error:
{
"data": null,
"errors": [
{
"message": "access denied",
"path": ["createVirtualDatacenter"]
}
]
}
Common causes and fixes:
| Symptom | Cause | Fix |
|---|---|---|
access denied on any query | Token expired or missing | Refresh your OIDC token |
access denied on VDC-scoped queries | Missing or wrong FlexPlane-VDC-ID header | Set the header to a VDC you have access to |
access denied on admin operations | User lacks ADMIN role | Request admin access from your tenant administrator |
access denied on VDC management | User lacks VDC_ADMIN role for target VDC | Request VDC admin access |
If you are unsure which role a field requires, check the schema. Every protected field has a @hasRole(role: [...]) directive listing the minimum required roles:
# Requires VDC_USER or higher
vms: [VM!] @hasRole(role: [VDC_USER])
# Requires ADMIN
createVirtualDatacenter(...): VirtualDatacenter! @hasRole(role: [ADMIN])
Handle validation errors
Input validation is enforced by the @constraint directive. When you send invalid input, the error message describes which constraint was violated:
{
"data": null,
"errors": [
{
"message": "validation failed: cpus must be min=1,max=64",
"path": ["addComputeProfile"]
}
]
}
Common validation constraints in the schema:
| Constraint | Meaning | Example |
|---|---|---|
required | Field must not be empty | name: String! @constraint(constraint: "required") |
min=N,max=N | Numeric range | cpus: Int! @constraint(constraint: "min=1,max=64") |
ipv4 | Must be a valid IPv4 address | ipv4: String @constraint(constraint: "ipv4") |
http_url | Must be a valid HTTP/HTTPS URL | checksumFile: String! @constraint(constraint: "http_url") |
hostname,max=N | Must be a valid hostname with max length | id: String! @constraint(constraint: "hostname,max=8") |
A well-structured client should:
- Check for the presence of the
errorsarray in every response. - If
errorsis present butdatais also non-null, handle the partial success case. - Display meaningful error messages to users based on the
messagefield. - For authorization errors, trigger a token refresh or redirect to login.
- For validation errors, highlight the relevant input field in your UI.