Skip to content

Subscription Update Token API fails due to _baseRequest expecting JSON response #3

@darshanpansuriya

Description

@darshanpansuriya

When calling the Subscription Update Token API using the _baseRequest method, the request sometimes fails with the following error:

Image
Error updating subscription token: FetchError: invalid json response body at 
https://subscriptions.solidgate.com/api/v1/subscription/update-token 
reason: Unexpected end of JSON input

Observed Behavior

  • The API call successfully updates the card token on the subscription.
  • However, the _baseRequest function calls res.json() in a .then() chain directly.
  • Since the update-token API returns an empty response body, .json() throws the Unexpected end of JSON input error.
  • As a result, the API call appears to fail, even though the token is updated correctly.

Root Cause

The _baseRequest method assumes all responses contain JSON.
For APIs that return no body, parsing as JSON fails.

Example of problematic code:

fetch(this.baseSolidGateUri + path, {
    method: 'POST',
    headers: {
        'Merchant': this.publicKey,
        'Signature': this._generateSignature(data),
        'Content-Type': 'application/json'
    },
    body: data
})
  .then(res => resolve(res.json())) // fails if response is empty
  .catch(err => reject(err));

Steps to Reproduce

  1. Call the update-token API via _baseRequest.
  2. Notice that the card token updates successfully.
  3. Observe that the promise rejects due to .json() failing on empty response.

Expected Behavior

  • _baseRequest should handle empty response bodies gracefully.
  • The API call should be considered successful when the card token updates, even if the response is empty.

Suggested Fix / Workaround

Modify _baseRequest to always read the response as text and then try parsing JSON, falling back to the raw text if parsing fails. For example:

fetch(this.baseSolidGateUri + path, {
    method: 'POST',
    headers: {
        'Merchant': this.publicKey,
        'Signature': this._generateSignature(data),
        'Content-Type': 'application/json'
    },
    body: data
})
  .then(res => res.text()) // always safe
  .then(text => {
      try {
          return resolve(text ? JSON.parse(text) : {}); 
      } catch {
          return resolve(text); // fallback if not JSON
      }
  })
  .catch(err => reject(err));

Benefits:

  • Works with empty responses.
  • Preserves JSON responses when they exist.
  • Compatible with .then()-based code without introducing async/await.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions