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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions