Fix: uploads.json
endpoint returns 500 internal server error
for some courses#6046
#6114
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What this PR does
Fixes the apparent cause of the 500 Internal server error in Issue #6046 and the subsequent
TypeError
it causes.Note: I could not replicate the error on my dev as only 138 uploads were imported out of the around 7000 after running updates multiple times. The 138 uploads loaded without error for me which I assume is because the problematic upload / file name
File%3AA+sunflower+%F0%9F%8C%BB%F0%9F%8C%BB+in+Kaduna+Polytechnic%2CSabo+Campus.jpg
was not imported.The commons link is here. It was uploaded by a user ‘Bambi Cia’ who has apparently deleted their user page / account. Trying to view their profile with this link, just shows loading: https://outreachdashboard.wmflabs.org/users/Bambi Cia because this request throws a 500 internal server error too: https://outreachdashboard.wmflabs.org/user_stats.json?username=Bambi Cia {"message":"Internal server error"}.
I used the test to verify this fix, and ran the updated code locally + used chrome dev tools to verify the TypeError fix works and doesn't break anything.
Fixing the 500 Error by allowing decoding of encoded strings
To fix this, I added
CGI.unescape
to decode such url encoded strings to their original formats:pretty = CGI.unescape(upload.file_name)
I then added another test in the
uploads_helper_spec.rb
to confirm it works.Before:
![b4](https://private-user-images.githubusercontent.com/92234322/402661554-aac52b97-3d2e-4511-b345-593af9972fd8.PNG?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkwNTA2NzcsIm5iZiI6MTczOTA1MDM3NywicGF0aCI6Ii85MjIzNDMyMi80MDI2NjE1NTQtYWFjNTJiOTctM2QyZS00NTExLWIzNDUtNTkzYWY5OTcyZmQ4LlBORz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMDglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjA4VDIxMzI1N1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWY0ZmMwYjcxMWQ0OTNlN2NkOTU3MDkwYzg5NDkwY2I3ODA4NmY3N2ViYWI5ZjFhZjAzMzU0NTJlNmUxOTMyMjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.ZbTuvzTa8xHbRwGbSSbTex8CLVtWQoimMDfUGLZGOXk)
After:
![afta](https://private-user-images.githubusercontent.com/92234322/402661683-123f17ea-cbe7-44d9-96e2-e0b5c1a30dc2.PNG?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkwNTA2NzcsIm5iZiI6MTczOTA1MDM3NywicGF0aCI6Ii85MjIzNDMyMi80MDI2NjE2ODMtMTIzZjE3ZWEtY2JlNy00NGQ5LTk2ZTItZTBiNWMxYTMwZGMyLlBORz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMDglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjA4VDIxMzI1N1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWVkMDIzZGJkNWFhZjI5OGNlMDc2MzliNjNkZDllZGU4ZmQ0YTMzZGNiN2I1ZGYwYTg2MmNlNWYxYWZkN2I1ZDYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.zua-LF4pw0-EHUFUQuw2izgaffiby2Fc8_t2lbikE14)
Fixing the resulting TypeError
When a 500 error occurs, the flow goes through the
.catch()
block inside thefetchUploads
function, andresp
is logged there. However, when the control goes back to the.then()
block,resp
is undefined because the promise is rejected and there is no valid response object passed.Then when the case
RECEIVE_UPLOADS
is reached in theuploads.js
reducer, theaction.data
will be undefined, and trying to accessaction.data.course.uploads
throws theTypeError: Cannot read properties of undefined('reading course'
.To prevent this, I:
?.
with a fallback to[]
so instead of throwing a TypeError when trying to access.course
on undefined or.uploads
on undefined, it evaluates to undefined. So ifaction.data?.course?.uploads
evaluates to undefined (because any part of the chain is missing),[]
is assigned todataUploads
:const dataUploads = action.data?.course?.uploads || [];
So when
dataUploads
is [],sortByKey
will return an empty array fornewModels
, and the reducer will update the state with an empty uploads array.I also:
Expanded the error handling in fetchUploads as when the 500 error occurs,
res
does not hold any relevant info other than the status being 500, (the status.text is an empty string) andError: undefined
is what is logged in the console.Added an explicit check for if
resp
is undefined, to explicitly state 'No response received.'