Skip to content
AF

Google Health API errors: the v4 error catalog and troubleshooting

Read from Google’s documentation on 2026-10-17 · discovery document revision 20261014 · Google’s error catalog last updated 2026-10-01

Google’s v4 error catalog lists 63 reasons across HTTP 400, 401, 403, 404, 409, 429 and 500, and adds: “This list contains some error messages related to its API, but is not a complete list of those messages.” The one a Fitbit Web API migration meets first is ACCOUNT_NOT_LINKED: HTTP 400 with status FAILED_PRECONDITION, when a user consents before their Google Account is linked to Google Health. Google says to call users.getIdentity right after the OAuth exchange and send the user to the Google Health app to link.

ACCOUNT_NOT_LINKED

Handle unlinked Google Accounts

A user must sign in to the Google Health mobile app to link Google Health to their Google Account before your app can sync data through the Google Health API. See Link Google Health before OAuth consent. Because Google OAuth 2.0 authenticates any valid Google Account during consent, it cannot block accounts that don't yet have an active Google Health profile.

If a user completes Google OAuth consent before creating a Google Health profile or before migrating their legacy Fitbit account to their Google Account, calling users.getIdentity or a data endpoint returns an HTTP 400 Bad Request error with status FAILED_PRECONDITION and reason ACCOUNT_NOT_LINKED:

{
  "error": {
    "code": 400,
    "message": "The account is not linked to Google Health.",
    "status": "FAILED_PRECONDITION",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "ACCOUNT_NOT_LINKED",
        "domain": "health.googleapis.com",
        "metadata": {
          "redirect_uri": "https://fitbit.google.com/auth/signup"
        }
      }
    ]
  }
}

To verify account access and handle this error:

  1. Exchange the OAuth authorization code for tokens and immediately call users.getIdentity (GET https://health.googleapis.com/v4/users/me/identity) before marking the account as linked in your app UI.
  2. If users.getIdentity or a background data sync call returns HTTP 400 with reason ACCOUNT_NOT_LINKED, don't mark the account as connected. If the user is migrating from the legacy Fitbit Web API, keep their existing Fitbit connection active and don't revoke their legacy Fitbit tokens.
  3. Display an actionable prompt that addresses both new users who have never created a Google Health or Fitbit account and existing Fitbit users who have not yet migrated to a Google Account:
    "Your Google Account isn't linked to Google Health yet. Open the Google Health mobile app and sign in with your Google Account to create a profile, or move your existing Fitbit account to your Google Account, then return here to connect."
  4. Provide a call-to-action button that opens the redirect_uri from the error metadata (https://fitbit.google.com/auth/signup) or direct legacy Fitbit users to the Fitbit account migration help article.

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

The catalog describes ACCOUNT_NOT_LINKED as “The Google account is not linked to a Fitbit account.”; the example response above carries the message “The account is not linked to Google Health.”. Both are Google’s text. Our suggestion: match on the reason, not the message.

The v4 error catalog

The following table lists HTTP status codes and associated errors that you might encounter when interacting with our API. Each status code corresponds to one or more reasons and descriptions to help you troubleshoot and handle errors effectively in your application. Within the descriptions, variables denoted by curly braces ({}) represent placeholders for values that are specific to your request.

Note: This list contains some error messages related to its API, but is not a complete list of those messages.

HTTP 400 (52)

ReasonGoogle’s description
ACCOUNT_NOT_LINKEDThe Google account is not linked to a Fitbit account.
INVALID_PARENT_DATA_TYPE_COLLECTION_FORMATInvalid {field} format. Expected: {expectedFormat}; Got: {actualValue}.
INVALID_PARENT_DATA_TYPE_COLLECTIONInvalid data type ID referenced in the parent data type collection: {dataType}.
INVALID_FILTER_FORMATInvalid filter format.
INVALID_DATA_POINT_DATA_SOURCE_FAMILYInvalid data source family in filter.
INVALID_DATA_POINT_FILTERInvalid filter.
INVALID_DATA_POINT_FILTER_SYNTAXInvalid filter syntax.
INVALID_DATA_POINT_FILTER_MISSING_TOKENInvalid filter: missing token.
INVALID_DATA_POINT_FILTER_UNEXPECTED_TOKENInvalid filter: unexpected token.
INVALID_DATA_POINT_FILTER_UNEXPECTED_END_OF_INPUTInvalid filter: unexpected end of input.
INVALID_DATA_POINT_FILTER_EXPRESSION_STRUCTUREInvalid filter expression structure.
INVALID_DATA_POINT_FILTER_RESTRICTION_COMPARABLEInvalid filter restriction comparable.
INVALID_DATA_POINT_FILTER_DATA_TYPE_RESTRICTIONInvalid filter data type restriction.
INVALID_TIME_RANGE_INTERVAL_FORMATCivil time provided for a non-daily rollup request or physical time provided for a daily rollup request.
INVALID_TIME_RANGEQuery end time must be strictly larger than start time.
INVALID_ROLLUP_QUERY_DURATIONThe duration covered by window_size_days * page_size must not exceed {maxDurationDays} days for {dataType}.
INVALID_ROLLUP_WINDOWRollup window size must be at least 1 second.
INVALID_DATA_POINT_FILTER_MIXED_DATA_TYPE_RESTRICTIONSFilter cannot contain restrictions for multiple data types.
INVALID_DATA_POINT_FILTER_MIXED_TIME_RESTRICTIONSFilter cannot contain both physical and civil time ranges.
INVALID_DATA_POINT_FILTER_DATA_TYPE_MEMBERInvalid filter member for data type.
INVALID_DATA_POINT_FILTER_RESTRICTION_COMPARATORInvalid filter restriction comparator.
INVALID_DATA_POINT_FILTER_TIMESTAMP_FORMATInvalid filter timestamp format.
INVALID_DATA_POINT_FILTER_CIVIL_DATE_TIME_FORMATInvalid filter civil date time format.
INVALID_CIVIL_DATE_TIMEInvalid civil date time: {reason}.
INVALID_DATA_POINT_FILTER_RESTRICTION_ARGUMENTInvalid filter restriction argument.
INVALID_DATA_POINT_FILTER_COLLECTION_MISMATCHData type in filter does not match parent data type collection.
INVALID_DATA_POINT_NAMEInvalid data point name.
DATA_POINT_NOT_OWNED_BY_CLIENTData point is not owned by the client.
MISSING_DATA_POINT_NAMESMissing data point names.
MISSING_DATA_POINT_FILTERFilter must be set for purge request.
DATA_TYPE_MISMATCHThe data point in the update request must have the same data type as the parent.
UPDATE_ONLY_UPSERT_SUPPORTEDUpdate only supports upsert. Please set allow_missing to true.
MISSING_DATA_POINT_IDMissing data point ID for update.
MISSING_DATA_POINT_VALUEMissing data point value.
INVALID_PROFILE_DATAInvalid value provided for field {field}. Provided value: {providedValue}. Accepted values: {acceptedValues}.
INVALID_FIELD_MASK_DATARequest contains invalid field mask data.
INVALID_PAGE_SIZEPage size cannot be negative, but was {actualValue}.
INVALID_PAGE_TOKENInvalid page token.
MULTIPLE_DATA_TYPES_UNSUPPORTEDMultiple data types are not supported.
UNSUPPORTED_DATA_TYPE_ACTIONThe action is not supported for the data type.
INVALID_DATA_TYPEInvalid data type provided: {dataType}.
MISSING_SUBSCRIBERSubscriber must be provided.
INVALID_SUBSCRIBER_NAMEInvalid subscriber name: {subscriberName}.
MISSING_SUBSCRIPTIONSubscription must be provided.
INVALID_SUBSCRIPTION_NAMEInvalid subscription name: {subscriptionName}.
MISSING_DATA_TYPESData types must be specified.
DATA_TYPES_CANNOT_BE_EMPTYData types cannot be empty. If you wish to stop receiving notifications, please use the DeleteSubscription API.
MISSING_USERUser field must be provided.
INVALID_USER_RESOURCE_NAMEInvalid user resource name: {userResourceName}.
INVALID_DATA_TYPE_FORMATData type must be all lowercase: {dataType}.
INVALID_ARGUMENTThe request is invalid.
FAILED_PRECONDITIONThe request cannot be completed in the current state.

HTTP 401 (1)

ReasonGoogle’s description
UNAUTHENTICATEDThe request is missing valid authentication credentials.

HTTP 403 (5)

ReasonGoogle’s description
MISSING_OAUTH_SCOPERequired OAuth scope(s) are missing for this operation.
DISALLOWED_OAUTH_SCOPESRequest contains disallowed OAuth scope(s): {disallowed_scopes}. Unrecognized scopes present: {unrecognized_scopes_present}.
API_PRIVATE_PREVIEW_ACCESS_DENIEDUser is not eligible for the API Private Preview.
DATA_ACCESS_DENIEDData can't be accessed.
RESOURCE_PERMISSION_DENIEDPermission denied for the requested resource.

HTTP 404 (1)

ReasonGoogle’s description
RESOURCE_NOT_FOUNDThe requested resource was not found.

HTTP 409 (2)

ReasonGoogle’s description
SLEEP_ALREADY_EXISTSA sleep log with an overlapping interval already exists.
ABORTEDThe operation was aborted.

HTTP 429 (1)

ReasonGoogle’s description
RESOURCE_EXHAUSTEDQuota exceeded or rate limited.

HTTP 500 (1)

ReasonGoogle’s description
INTERNAL_ERRORAn internal error occurred.

Quoted from Google's v4 error catalog, last updated 2026-10-01, read 2026-10-17.

Google’s troubleshooting tables

400 Bad Request

MessageDescriptionRecommendation
Request contains an invalid argument.The data type ID {value} is not supported.Verify the data type being referenced is supported by the endpoint.
Invalid JSON payload received. Octal/hex numbers are not valid JSON values.The dailyRollUp endpoint does not support month and day values represented as MM or DD, respectfully. Single digits shouldn't have a leading 0 (zero).
Your client has issued a malformed or illegal request.Possible causes:
Verify the correct HTTP method is being used

Check the endpoint syntax for typos
Invalid project number in resource nameWhen deleting or updating a subscriber using your Google Cloud project ID in the request URL instead of project number. This applies to webhook subscriptions using the projects.subscribers endpoint.Use your Google Cloud project number in the request URL, not the project ID.
The account is not linked to Google Health.Status: FAILED_PRECONDITION
Reason: ACCOUNT_NOT_LINKED

The user authorized your app through Google OAuth, but their Google Account does not have an active Google Health profile (either they have never set up Google Health or have not migrated their legacy Fitbit account).
Call users.getIdentity immediately after exchanging the authorization code to verify account linking. If this error occurs, don't mark the account as connected. Instead, prompt the user to sign in to the Google Health mobile app or open the redirect_uri (https://fitbit.google.com/auth/signup). See Handle unlinked Google Accounts.

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

401 Unauthorized

MessageDescriptionRecommendation
Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.INVALID_AUTHENTICATOR: Token expiredYour access token has expired. Use the refresh token to obtain a new access token & refresh token, or the user should re-consent to the application.

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

403 Forbidden

MessageDescriptionRecommendation
The caller does not have permissionWhen creating or listing subscribers using your Google Cloud project ID in the request URL instead of project number. This applies to webhook subscriptions using the projects.subscribers endpoint.Use your Google Cloud project number in the request URL, not the project ID.
The caller does not have permission.Could not mint UberMint from GaiaMint.The user was able to complete the authorization flow, but the endpoint call failed. This can occur when a legacy Fitbit account consents to the app instead of a Google Account. To resolve this error:
Sign out of the Google Health app through the settings.

Sign into the Google Health app either by pressing the "Continue with Google" or "Sign in with Google" button. If you receive a message that states "Can't use Fitbit with this Google Account", your email address is still registered as a legacy Fitbit account. Follow the steps in this help article to migrate your account.

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

404 Not Found

MessageDescriptionRecommendation
The requested URL /v4/users/me/dataTypes/{dataType}/dataPoints was not found on this server.Possible causes:
Verify the correct verb is being used

Check the endpoint syntax for typos

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

Supporting a user

Retrieve a Fitbit user ID

To help troubleshoot a user issue, you may need to verify the Google Account of the user logged into the Google Health app.

To find the legacy Fitbit user ID:

  1. Open the Google Health app.
  2. Press the Health icon in the bottom right hand corner.
  3. In the "Personal info" section, press Profile.
  4. In the "Account information" section, the value assigned to the ID is the legacy Fitbit user ID. (For example: CV5TKH)

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

Troubleshoot device syncing delays

When debugging issues related to missing or delayed user data, it is helpful to check the user's paired device model and their last synchronization date.

The model information (such as a Fitbit tracker or smartwatch model) and last sync date are useful for troubleshooting and to fetch historical data after syncing delays.

For example, if you notice an unexpected gap or delay in data delivery:

  1. Verify that the user ID you are querying matches the user ID of the Fitbit account logged into the mobile app. To obtain the user ID in the mobile app, see Retrieve a Fitbit user ID. To obtain the user ID from the access token, call the getIdentity endpoint.
  2. Check the last sync time to determine when the user's device last synced with the Google Health mobile app.
  3. If the device has not synced recently, it indicates that the delay is likely due to the device being offline or not syncing with the mobile application, rather than an API issue.
  4. Once the user opens the mobile application and syncs their device, you can fetch historical data for the period since the last sync time.

To retrieve a user's paired device information, call the users.pairedDevices.list endpoint. This returns a list of devices containing:

  • deviceVersion: The product name or model of the device (for example, "Charge 6").
  • lastSyncTime: The timestamp of the last successful synchronization.

Quoted from Google's troubleshooting guide, last updated 2026-09-28, read 2026-10-17.

Errors from webhook subscriber calls are on the webhooks page; 429 and quota handling on access and rate limits. The Fitbit Web API’s own errors: Fitbit error code 401.

Questions

What does ACCOUNT_NOT_LINKED mean in the Google Health API?

The user's Google Account is not linked to Google Health yet. If a user completes Google OAuth consent before creating a Google Health profile or before migrating their legacy Fitbit account to their Google Account, calling users.getIdentity or a data endpoint returns an HTTP 400 Bad Request error with status FAILED_PRECONDITION and reason ACCOUNT_NOT_LINKED: Google's fix: Exchange the OAuth authorization code for tokens and immediately call users.getIdentity (GET https://health.googleapis.com/v4/users/me/identity) before marking the account as linked in your app UI. The v4 error catalog's own description of ACCOUNT_NOT_LINKED (HTTP 400) reads: "The Google account is not linked to a Fitbit account."

What does "Could not mint UberMint from GaiaMint" mean in the Google Health API?

Google's troubleshooting guide lists it under 403 Forbidden: The caller does not have permission. — Could not mint UberMint from GaiaMint. — The user was able to complete the authorization flow, but the endpoint call failed. This can occur when a legacy Fitbit account consents to the app instead of a Google Account. To resolve this error: Sign out of the Google Health app through the settings. Sign into the Google Health app either by pressing the "Continue with Google" or "Sign in with Google" button. If you receive a message that states "Can't use Fitbit with this Google Account", your email address is still registered as a legacy Fitbit account. Follow the steps in this help article to migrate your account.

Why does a Google Health API dataPoints request return 404 Not Found?

Google's troubleshooting guide: The requested URL /v4/users/me/dataTypes/{dataType}/dataPoints was not found on this server. — — Possible causes: Verify the correct verb is being used Check the endpoint syntax for typos

Why does a Google Health API subscriber call fail with "Invalid project number in resource name"?

Google's troubleshooting guide: Invalid project number in resource name — When deleting or updating a subscriber using your Google Cloud project ID in the request URL instead of project number. This applies to webhook subscriptions using the projects.subscribers endpoint. — Use your Google Cloud project number in the request URL, not the project ID.

What does SLEEP_ALREADY_EXISTS mean in the Google Health API?

Google's v4 error catalog lists SLEEP_ALREADY_EXISTS with HTTP 409: "A sleep log with an overlapping interval already exists."

Sources checked

Google’s text is quoted for identification; each guide page’s footer reads: “Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License.”. Generated from Google’s pages by scripts/fetch-google-health-api.mjs, not typed by hand; Google’s documentation remains the authority.