Skip to content

PATCH /datalab/v1beta1/regions/{region}/datalabs/{id} returns uninitialized object and does not persist changes #3002

@sbx0r

Description

@sbx0r

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:

  1. Returns an empty/zero-value response body (HTTP 200)
  2. 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.tool

Raw 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

  1. The PATCH response body is an uninitialized/zero-value Datalab object. All fields are empty strings, nulls, or zero values. The id field is "" and status is "unknown_status". This is 247 bytes vs the typical 930+ bytes for a properly populated response.

  2. The PATCH does not persist changes. A subsequent GET of the same resource returns the original, unmodified values. The name, description, and tags sent in the PATCH body are silently discarded.

Expected behavior

  1. PATCH applies the requested changes to the Datalab resource
  2. PATCH returns the fully populated, updated Datalab object (consistent with POST, GET, DELETE)

Actual behavior

  1. PATCH does not apply changes (GET after PATCH shows original values)
  2. PATCH returns an uninitialized Datalab object (all zero values)
  3. 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:

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions