--update-mask is documented on every writable type's update subcommand, but the v4 API has no such field on the PATCH request message, so passing the flag always fails with a 400.
Reproduction
Straight from the CLI, no custom tooling, on weight (already Writable: true with update support):
$ ghealth data weight create --json '{"weight":{"weightGrams":1234,"notes":"repro - delete me","sampleTime":{"physicalTime":"2026-09-03T18:00:00Z","utcOffset":"-18000s"}}}'
# -> created id 1919002790956405426
$ ghealth data weight update --id 1919002790956405426 \
--json '{"weight":{"weightGrams":4321}}' \
--update-mask weight.weightGrams
{
"error": {
"type": "api",
"code": 1,
"status": 400,
"message": "Invalid JSON payload received. Unknown name \"updateMask\": Cannot bind query parameter. Field 'updateMask' could not be found in request message."
}
}
$ ghealth data weight update --id 1919002790956405426 \
--json '{"weight":{"weightGrams":4321,"sampleTime":{"physicalTime":"2026-09-03T18:00:00Z","utcOffset":"-18000s"}}}'
# -> 200 OK, weightGrams now 4321
Same result with snake_case (?update_mask=...) sent directly to the API, so it isn't a casing mismatch in cmd/data.go:
400 Invalid JSON payload received. Unknown name "update_mask": Cannot bind query parameter.
Test data was deleted afterwards and confirmed gone (404).
Cause
newUpdateCommand in cmd/data.go sets the mask as a query parameter:
if updateMask != "" {
req.Query = url.Values{"updateMask": {updateMask}}
}
The API rejects it because users.dataTypes.dataPoints.patch has no updateMask in its request message — the v4 discovery document lists no query parameters for that method at all. So the flag can only ever turn a working request into a 400.
Suggested fix
Either drop --update-mask, or keep it and fail fast client-side with a clear message rather than sending a request that is guaranteed to 400. Worth a line in the README's write section too, since the current wording implies partial updates are supported — PATCH appears to be whole-object, which matters because a partial body silently drops the fields you leave out.
Happy to send a PR for whichever you prefer.
Environment
ghealth built from main @ 9cf0274, go build -o ghealth .
- go1.26.0 linux/amd64
--update-maskis documented on every writable type'supdatesubcommand, but the v4 API has no such field on the PATCH request message, so passing the flag always fails with a 400.Reproduction
Straight from the CLI, no custom tooling, on
weight(alreadyWritable: truewithupdatesupport):Same result with snake_case (
?update_mask=...) sent directly to the API, so it isn't a casing mismatch incmd/data.go:Test data was deleted afterwards and confirmed gone (404).
Cause
newUpdateCommandincmd/data.gosets the mask as a query parameter:The API rejects it because
users.dataTypes.dataPoints.patchhas noupdateMaskin its request message — the v4 discovery document lists no query parameters for that method at all. So the flag can only ever turn a working request into a 400.Suggested fix
Either drop
--update-mask, or keep it and fail fast client-side with a clear message rather than sending a request that is guaranteed to 400. Worth a line in the README's write section too, since the current wording implies partial updates are supported — PATCH appears to be whole-object, which matters because a partial body silently drops the fields you leave out.Happy to send a PR for whichever you prefer.
Environment
ghealthbuilt frommain@ 9cf0274,go build -o ghealth .