-
Notifications
You must be signed in to change notification settings - Fork 55
PATCH /datalab/v1beta1/regions/{region}/datalabs/{id} returns uninitialized object and does not persist changes #3002
Description
Warning
This is an API-side issue, not an SDK bug.
I couldn't find a better place to report it.
Please redirect if there's a more appropriate channel.
Description
While building the Terraform provider for scaleway_datalab (using the Datalab v1beta1 API), we discovered that the PATCH endpoint for updating a Datalab instance:
- Returns an empty/zero-value response body (
HTTP 200) - Does not persist the requested changes
This is the only endpoint across the entire Scaleway API surface that exhibits this behavior - all other services (VPC, RDB, K8s, Container, MongoDB, Block, etc.) return fully populated updated resources from their PATCH endpoints.
Testing method
export SCW_SECRET_KEY="[REDACTED]"
# 1. Assume a Datalab in "ready" state exists
export DATALAB_ID="<datalab-id>"
# 2. `GET` current state
curl -s -H "X-Auth-Token: $SCW_SECRET_KEY" \
"https://api.scaleway.com/datalab/v1beta1/regions/fr-par/datalabs/$DATALAB_ID" \
| python3 -m json.tool
# 3. `PATCH` to update name, description, and tags
curl -s -X PATCH \
-H "X-Auth-Token: $SCW_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"renamed","description":"updated","tags":["new-tag"]}' \
"https://api.scaleway.com/datalab/v1beta1/regions/fr-par/datalabs/$DATALAB_ID" \
| python3 -m json.tool
# 4. `GET` again - changes are NOT persisted
curl -s -H "X-Auth-Token: $SCW_SECRET_KEY" \
"https://api.scaleway.com/datalab/v1beta1/regions/fr-par/datalabs/$DATALAB_ID" \
| python3 -m json.toolRaw evidence from live API calls
All requests below target Datalab 908fa4db-155b-442e-9775-a9ee7053168b in fr-par, executed on 2026-03-24.
GET before PATCH (baseline)
{
"id": "908fa4db-155b-442e-9775-a9ee7053168b",
"status": "ready",
"project_id": "[REDACTED]",
"name": "patch-bug-test",
"description": "",
"tags": [],
"created_at": "2026-03-24T13:46:54.776394Z",
"updated_at": "2026-03-24T13:52:42.421265Z",
"main": {
"node_type": "DATALAB-SHARED-4C-8G",
"spark_ui_url": "https://908fa4db-155b-442e-9775-a9ee7053168b.ddl.fr-par.scw.cloud:4040",
"spark_master_url": "spark://master-datalab-908fa4db-155b-442e-9775-a9ee7053168b.e5d06d86-b4b3-4d4d-b105-81c8f6755fcc.internal:7077",
"root_volume": { "type": "sbs_5k", "size": 50000000000 }
},
"worker": {
"node_type": "DATALAB-DEDICATED2-2C-8G",
"node_count": 1,
"root_volume": { "type": "sbs_5k", "size": 50000000000 }
},
"has_notebook": false,
"spark_version": "4.0.0",
"total_storage": { "type": "unknown_type", "size": 0 },
"private_network_id": "e5d06d86-b4b3-4d4d-b105-81c8f6755fcc",
"region": "fr-par"
}PATCH request and response
Request body:
{"name":"renamed-for-bug-report","description":"updated description","tags":["new-tag"]}Response (200 OK, 247 bytes):
{
"id": "",
"status": "unknown_status",
"project_id": "",
"name": "",
"description": "",
"tags": [],
"created_at": null,
"updated_at": null,
"main": null,
"worker": null,
"has_notebook": false,
"spark_version": "",
"total_storage": null,
"private_network_id": "",
"region": ""
}Every field is a zero/default value. Compare with the fully populated GET response above.
GET after PATCH (confirms changes NOT persisted)
{
"id": "908fa4db-155b-442e-9775-a9ee7053168b",
"status": "ready",
"project_id": "[REDACTED]",
"name": "patch-bug-test",
"description": "",
"tags": [],
"created_at": "2026-03-24T13:46:54.776394Z",
"updated_at": "2026-03-24T13:52:42.421265Z",
"region": "fr-par"
}Name is still "patch-bug-test" (not "renamed-for-bug-report"), description is still "" (not "updated description"), tags is still [] (not ["new-tag"]). The updated_at timestamp is unchanged, confirming no server-side mutation occurred.
Two separate bugs
-
The
PATCHresponse body is an uninitialized/zero-valueDatalabobject. All fields are empty strings, nulls, or zero values. Theidfield is""andstatusis"unknown_status". This is 247 bytes vs the typical 930+ bytes for a properly populated response. -
The
PATCHdoes not persist changes. A subsequentGETof the same resource returns the original, unmodified values. The name, description, and tags sent in the PATCH body are silently discarded.
Expected behavior
PATCHapplies the requested changes to the Datalab resourcePATCHreturns the fully populated, updatedDatalabobject (consistent withPOST,GET,DELETE)
Actual behavior
PATCHdoes not apply changes (GETafterPATCHshows original values)PATCHreturns an uninitializedDatalabobject (all zero values)- Returns
HTTP 200, giving no indication of failure
Impact on SDK consumers
The Go SDK deserializes the PATCH response into a Datalab struct. Because region is "", scw.ParseRegion() fails with:
- validation/is.go:42-45:
could not parse application/json response body: - scw/locality.go:193:
bad region format, available regions are: fr-par, nl-ams, pl-waw, it-mil
This makes (*datalab.API).UpdateDatalab() unusable and blocks the Terraform provider from implementing in-place updates (name, description, tags, worker node_count).
Comparison with other APIs
Every other Update/PATCH method across the Scaleway API returns a fully populated resource:
| API | Endpoint | PATCH returns populated resource? |
|---|---|---|
| VPC v2 (stable) | UpdateVPC |
Yes |
| RDB v1 (stable) | UpdateInstance |
Yes |
| K8s v1 (stable) | UpdateCluster |
Yes |
| Container v1beta1 | UpdateContainer |
Yes |
| MongoDB v1 (beta) | UpdateInstance |
Yes |
| Block v1alpha1 | UpdateVolume |
Yes |
| Datalab v1beta1 | UpdateDatalab |
No - zeroed object |