ropensci / qualtRics

Download ⬇️ Qualtrics survey data directly into R!
https://docs.ropensci.org/qualtRics
Other
215 stars 70 forks source link

Qualtrics unable to assist with internal server (500) error. #274

Closed asadow closed 1 year ago

asadow commented 2 years ago

I contacted Qualtrics, provided my endpoint URL and survey ID's. This was their response:

I ran the call on my end based on the information and found that the call ran successfully.

However, I can confirm that this is the correct endpoint URL that you should be using:

GET 'https://uoguelph.eu.qualtrics.com/API/v3/survey-definitions/SV_2rF0CcmMF1MmTiJ'

I can also confirm that the call is capable of being ran successfully if you use the above endpoint URL and the correct API token (The one from your account).

Can you double check that you're using the same endpoint URL?

I believe I am using this endpoint URL, but am not sure. I constructed it from:

BrandBaseURL https://uoguelph.eu.qualtrics.com/ + /API/v3/survey-definitions/ +

SurveyID SV_2rF0CcmMF1MmTiJ

How may I verify my endpoint URL?

juliasilge commented 2 years ago

It looks like you are calling fetch_description(); is that right? You can check the URL like this but using your own survey ID:

qualtRics:::generate_url("fetchdescription", surveyID = "SV_xxxxx")
#> https://conjoint.co1.qualtrics.com/API/v3/survey-definitions/SV_xxxxx/

Created on 2022-07-25 by the reprex package (v2.0.1)

What does it look like when you call that code with your own info? Can you tell me more about the error you are seeing in R?

asadow commented 2 years ago

Thank you! I get

> qualtRics:::generate_url("fetchdescription", surveyID = df_errored$id)
https://fra1.qualtrics.com/API/v3/survey-definitions/SV_ezFnmDF8xXheiR7/
> fetch_survey(df_errored$id)

|===================================================================================================| 100%

── Column specification ─────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_character(),
  StartDate = col_datetime(format = ""),
  EndDate = col_datetime(format = ""),
  Progress = col_double(),
  `Duration (in seconds)` = col_double(),
  Finished = col_logical(),
  RecordedDate = col_datetime(format = ""),
  ExternalReference = col_double(),
  LocationLatitude = col_double(),
  LocationLongitude = col_double(),
  Q5 = col_double(),
  Q7 = col_double(),
  Q8 = col_double(),
  Q195_10_TEXT = col_logical(),
  Q296_7_TEXT = col_logical(),
  Q175_10 = col_logical(),
  Q250_2 = col_logical(),
  Q250_7 = col_logical(),
  Q250_8 = col_logical(),
  Q250_13 = col_logical(),
  Q250_14 = col_logical()
  # ... with 237 more columns
)
ℹ Use `spec()` for the full column specifications.

Request failed [500]. Retrying in 1 seconds...
Request failed [500]. Retrying in 3.3 seconds...
Request failed [500]. Retrying in 4.3 seconds...
Error in `qualtrics_response_codes()`:
! Qualtrics API reports a temporary internal server (500) error.
• Please contact Qualtrics Support or retry your query
• instanceId: 83f557a4-ecbd-417a-96ff-c0cd003cc3ab
• errorCode: ST_2.0
Run `rlang::last_error()` to see where the error occurred.

> rlang::last_error()
<error/rlang_error>
Error in `qualtrics_response_codes()`:
! Qualtrics API reports a temporary internal server (500) error.
• Please contact Qualtrics Support or retry your query
• instanceId: 83f557a4-ecbd-417a-96ff-c0cd003cc3ab
• errorCode: ST_2.0
---
Backtrace:
 1. qualtRics::fetch_survey(df_errored$id)
 2. qualtRics:::infer_data_types(data, surveyID)
 4. qualtRics::metadata(surveyID, get = "questions")
 5. qualtRics:::qualtrics_api_request("GET", survey_url)
 6. qualtRics:::qualtrics_response_codes(res)
Run `rlang::last_trace()` to see the full context.
juliasilge commented 2 years ago

Do you have your datacenter-specific base URL set correctly? I notice that you have fra1.qualtrics.com but it sounds like Qualtrics support said you should be using uoguelph.eu.qualtrics.com.

asadow commented 2 years ago

Yes, either of the two works, but there is still the above error (albeit with a different instanceId).

juliasilge commented 2 years ago

I feel a bit confused still about which endpoint you are having trouble with, because the first info you shared was about fetching the description and the second was about fetch_survey(). Can you create a reprex (a minimal reproducible example) for the specific problem you are facing? The goal of a reprex is to make it easier for us to recreate your problem so that we can understand it and/or fix it. If you've never heard of a reprex before, you may want to start with the tidyverse.org help page. Thanks! 🙌

asadow commented 2 years ago

Thanks Julia. I'll need to get permission to share a reprex with a secret. I will work on that!

You helped me verify my endpoint URL. So maybe I should open another issue?

Both fra1.qualtrics.com and uoguelph.eu.qualtrics.com can be used but return the same error. The real issue at hand is getting the subject titled error when using fetch_survey(). This was Qualtrics' support's reponse:

Because the call for the survey is working successfully on our end using your information, and we aren't able to support R code, we unfortunately don't have additional visibility into this.

For visibility, this is the call that was ran successfully on our end:

curl --location --request GET 'https://uoguelph.eu.qualtrics.com/API/v3/survey-definitions/SV_2rF0CcmMF1MmTiJ' \ --header 'X-API-TOKEN: [API TOKEN]' \ --header 'Content-Type: application/json'

Does this endpoint URL look like the endpoint URL that you're using?

This is the cURL of the call that I ran successfully, the cURL is in JSON, and you can pull the endpoint URL that I used from this cURL code.

If you can confirm that you're using a different endpoint URL and receiving the error, then I could try to run the call with that endpoint URL as well!

Reprex without secret:

id_subset = "SV_bQ1k3sEqxrXN71P"
qualtRics:::generate_url("fetchdescription", surveyID = id_subset)
#> https://fra1.qualtrics.com/API/v3/survey-definitions/SV_bQ1k3sEqxrXN71P/
qualtRics:::fetch_survey(id_subset)
#>   |                                                                              |                                                                      |   0%  |                                                                              |=========================                                             |  36%  |                                                                              |===================================================                   |  72%  |                                                                              |======================================================================| 100%
#> 
#> ── Column specification ────────────────────────────────────────────────────────
#> cols(
#>   .default = col_character(),
#>   StartDate = col_datetime(format = ""),
#>   EndDate = col_datetime(format = ""),
#>   Progress = col_double(),
#>   `Duration (in seconds)` = col_double(),
#>   Finished = col_logical(),
#>   RecordedDate = col_datetime(format = ""),
#>   ExternalReference = col_double(),
#>   LocationLatitude = col_double(),
#>   LocationLongitude = col_double(),
#>   Q3.3 = col_double(),
#>   Q3.4 = col_double(),
#>   Q3.5 = col_double(),
#>   Q3.6_10_TEXT = col_logical(),
#>   Q4.5 = col_double(),
#>   Q4.7 = col_double(),
#>   Q5.2_10 = col_logical(),
#>   Q6.1_8 = col_logical(),
#>   Q6.1_22 = col_logical(),
#>   Q7.5 = col_double(),
#>   Q12.3 = col_time(format = "")
#>   # ... with 143 more columns
#> )
#> ℹ Use `spec()` for the full column specifications.
#> Error in `qualtrics_response_codes()`:
#> ! Qualtrics API reports an internal server (500) error. Please contact
#> Qualtrics Support (https://www.qualtrics.com/contact/) and provide the instanceId and errorCode below.
#> 
#> instanceId: a29b4d9e-82b3-4b1c-8d49-444e51df212a
#> errorCode: ST_2.0

Created on 2022-08-19 by the reprex package (v2.0.1)

juliasilge commented 2 years ago

No need to share the secret! For API calls like this, the reprex just helps a lot, even without me being able to literally run your API call.

For this API call, fetchdescription does not give the relevant URL. (I had assumed that was what you were having trouble with because above you showed GET 'https://uoguelph.eu.qualtrics.com/API/v3/survey-definitions/SV_2rF0CcmMF1MmTiJ' earlier in the thread.)

Instead what you want is (with your surveyID):

qualtRics:::generate_url("exportresponses", surveyID = "SV_3gbwxxx")
#> https://conjoint.co1.qualtrics.com/API/v3/surveys/SV_3gbwxxx/export-responses/

Created on 2022-08-19 with reprex v2.0.2

That would be the URL to share with Qualtrics, together with the instanceId and errorCode. You are doing a POST request from R with that URL.

asadow commented 2 years ago

Apologies, I will start with a reprex next time.

I get an error when attempting to generate the URL:

id_subset = "SV_bQ1k3sEqxrXN71P"
qualtRics:::generate_url("exportresponses", surveyID = id_subset)
#> Error in `qualtRics:::generate_url()`:
#> ! Internal error: invalid URL generation query

Created on 2022-08-19 by the reprex package (v2.0.1)

juliasilge commented 2 years ago

Ah, my apologies -- you will need to install from GitHub to get that URL:

remotes::install_github("ropensci/qualtRics")

Are you able to install from GitHub? If not, I can install back to the last CRAN version to remember what that was.

asadow commented 2 years ago

Yes, I'm able, and I get what looks like the endpoint they used. I will send Qualtrics support this in case I'm wrong! Thank you so much.

id_subset = "SV_bQ1k3sEqxrXN71P"
qualtRics:::generate_url("exportresponses", surveyID = id_subset)
#> https://uoguelph.eu.qualtrics.com/API/v3/surveys/SV_bQ1k3sEqxrXN71P/export-responses/

Created on 2022-08-19 by the reprex package (v2.0.1)

Aside: I'm curious why you asked if able to install from GitHub; is it because it is considered less safe, so some institutions prevent it?

juliasilge commented 2 years ago

Yep, some orgs have high compliance/reporting needs in terms of software versions and so don't allow folks to install from GitHub.

asadow commented 2 years ago

Hi Julia,

I got a response from Qualtrics - yay! However they are now asking if I'd like something else and I am a bit confused as to how to provide it, if possible. Their response is below.

Upon investigation from our internal team, we have confirmed that the issue is occurring for the API calls below:

[...]/API/v3/surveys/[sv_id1] [...]/API/v3/surveys/[sv_id2]

These are GET Survey API calls and the reason they are failing is because the survey size is too big. Upon testing, it seems that deleting the 113 question Loop and Merge block enabled the call to succeed.

In regards to the API calls below for POST Export Responses, we are still unable to replicate the issue which means this call is succeeding on our end. Could you provide the instance ID and complete error message for this call as well?

[...]/API/v3/surveys/[sv_id]/export-responses/

In regards to the error below, it seems that this is using the API call for API/v3/surveys/ and not export response.

Error in qualtrics_response_codes():! After 4 attempts, Qualtrics API reported a temporary internal server error (500):• Please contact Qualtrics Support or retry your query• instanceId: 964006a0-2e03-4f0d-b874-b8f4352b9d14• errorCode: ST_2.0Run rlang::last_error() to see where the error occurred.

As previously mentioned, this endpoint is failing due to the survey size and cutting the length of the survey would help the call to succeed.

If you would like for us to investigate the export response API call, would you be able to make this call again, provide the error details as above and a screenshot of the call and the response body as well?

juliasilge commented 2 years ago

I'm not totally sure what's going on, but I hope that this can help you.

If you are calling fetch_survey(), you first make a POST request to:

qualtRics:::generate_url("exportresponses", surveyID = "SV_3gbwq8aJgqPwQDP")
#> https://conjoint.co1.qualtrics.com/API/v3/surveys/SV_3gbwq8aJgqPwQDP/export-responses/

Created on 2022-09-01 with reprex v2.0.2

This gives you a requestID. After that you make a GET request (for the progress) to:

qualtRics:::generate_url("exportresponses_progress", surveyID = "SV_3gbwq8aJgqPwQDP", requestID = "[request_id]")
#> https://conjoint.co1.qualtrics.com/API/v3/surveys/SV_3gbwq8aJgqPwQDP/export-responses/[request_id]

Created on 2022-09-01 with reprex v2.0.2

This gives you a file ID and last you make a GET request (for the export file) to:

qualtRics:::generate_url("exportresponses_file", surveyID = "SV_3gbwq8aJgqPwQDP", fileID = "[file_id]")
#> https://conjoint.co1.qualtrics.com/API/v3/surveys/SV_3gbwq8aJgqPwQDP/export-responses/[file_id]/file

Created on 2022-09-01 with reprex v2.0.2

If you are having trouble with something in those sequence of three API calls...

## gives you the requestID:
qualtRics:::export_responses_init(
  surveyID = "SV_3gbwq8aJgqPwQDP", 
  body = '{"format":"csv","useLabels":true,"includeDisplayOrder":true,"breakoutSets":true} '
  )
#> [1] "ES_3VMwSTCY9jq1Dlc"

Created on 2022-09-01 with reprex v2.0.2

## gives you the fileID:
qualtRics:::export_responses_progress(
  surveyID = "SV_3gbwq8aJgqPwQDP", 
  requestID = "ES_6lZiPieVXQP2IDQ"
  )
#> [1] "f8e55497-b29e-40ee-bd25-a2bf7b23cff4-def"

Created on 2022-09-01 with reprex v2.0.2

## downloads the file and returns the path:
qualtRics:::export_responses_filedownload(
  surveyID = "SV_3gbwq8aJgqPwQDP", 
  fileID = "f8e55497-b29e-40ee-bd25-a2bf7b23cff4-def"
  )
#> [1] "/var/folders/hv/hzsmmyk9393_m7q3nscx1slc0000gn/T//Rtmp7Y7T74/Beskar Armor.csv"

Created on 2022-09-01 with reprex v2.0.2

juliasilge commented 1 year ago

Let us know if you have further questions! 🙌