HTTP.call throws errors instead of returning response - meteor

I am working with the Facebook graph API and have run into trouble regarding handling failed requests.
I use this code to create a new post
SocialFacebook.createPosting = function(data) {
var options = {
params: {
access_token : data.tokens.accessToken,
message : data.text
}
};
var url = 'https://graph.facebook.com/' + data.graphId + '/feed';
var response = HTTP.call('POST', url, options).data;
return response;
}
But instead of returning a JS object with error information in the response, it throws an error on failed requests
Exception while invoking method 'createPosting' Error: failed [500] {"error":{"message":"Duplicate status message","type":"FacebookApiException","code":506,"error_subcode":1455006,"is_transient":false,"error_user_title":"Duplicate Status Update","error_user_msg":"This status update is identical to the last one you posted. Try posting something different, or delete your previous update."}}
Because it's wrapped in an Error, the otherwise JSON object is now a string with some other stuff appended to it, which makes it difficult to parse and extract the attributes
Any idea as to why it throws an error, instead of returning a JS object with error details like usually?
Much appreciated

According to the docs, about HTTP.call():
On the server, this function can be run either synchronously or asynchronously. If the callback is omitted, it runs synchronously and the results are returned once the request completes successfully. If the request was not successful, an error is thrown.
So there you have it: since you called HTTP.call() synchronously (without providing a callback), if it responds with an error (in your case, Code 500) the error is thrown and not included in the data.

Related

Accessing response error data in next.js using SWR

I have a form data which on submit I a sending to backend if there is an error I have process the error and show it on page. Request is getting posted fine but when getting a backend response I never go to catch error loop. Appreciate any help in resolving this.
Thanks
const [errorMessage, setErrorMessage] = useState('')
mutate(
`${api}`,
fetcher('POST', `${api`, body: JSON.stringify(data))
)
.then((data) => {
... do something
})
.catch((error) => {
setErrorMessage(data.error.message)
console.error(error)
})
}
backend response data :
{"trace_id":"abc","errors":[{"code":122,"message":" Error While
Submitting."}]}
The .catch clause will only fire if there is an error executing the network request. But in this case, it's working - it sends a request and gets a response. So only the then clause is fired. However, the response contains an error.
There are a few ways to make it so the error response gets 'caught' - either you configure your graphql library to look inside each response to check for 'errors' property to be non-empty and throw, or you can do that inside the then clause in your example.

How to access backend errors with Redux createAsyncThunk

I am not sure how I am supposed to get the errors that come from the backend when a POST request is sent to the backend. If I use plain axios calls, I can simply get the errors from the response object in the catch block with:
error.response.data.errors
But when using Redux and using createAsyncThunk method, on a 400 status code from the server, a rejected action is dispatched and the error object I get is a generic one like so:
{
message: "Request failed with status code 400"
name: "Error"
stack: "Error: Request failed with status code 400\n...."
}
How can I get the server errors, just like using axios?
You can make use of the rejectWithValue function from redux-toolkit to include the server error as the payload property of your rejected action.
It would be something like this (untested code because I’m on my phone)
const myAction = createAsyncThunk(
‘actionName’,
async ( arg, {rejectWithValue} ) => {
try {
const res = await axios.post(…);
return res.data;
} catch (error) {
return rejectWithValue( error.response.data.errors );
}
});
I think what you can do is add an additional check for the errors and also wrap the axios post request with a try catch block.
Note : In your case the request is failing so I guess there must be some error with the way you are making a request.

Meteor publication send custom sanitized error to client in publication

I am not sure if I am just doing something wrong or if this is actually not working. I want to display the original publication error on the client, in case I catched one:
Meteor.publish('somePub', function (args) {
const self = this
try {
// ... publication logic
catch (pubErr) {
self.error(pubErr)
}
})
On the client I am "catching" this error via the onStop callback:
Meteor.subscribe('somePub', args, {
onStop: function (e) {
// display e to user
}
})
However, while on the server the pubErr is a Meteor.Error and according to the documentation it should be sent to the client, the client just receives a generic sanitized error message:
on the server
{
stack: "useful stack of actual method calls",
error: "somePub.failed",
reason: "somePub.invalidArguments",
details: { arg: undefined }
}
on the client
{
stack: "long list of ddp-message calls",
isClientSafe: true,
error: 500,
reason: "Internal server error",
details: undefined,
message: "Internal server error [500]",
errorType: "Meteor.Error"
}
Note: I also tried to add the error to itself as sanitizedError field, as in the documentation mentioned, but no success either.
Am I missing something here?
Actually I found the answer to the issue after being pointed into the right direction.
The example code works fine on a new project, so I checked why not in my project and I found, that I did not surround the arguments validation using SimpleSchema by the try/catch (unfortunately my question was poorly designed as it missed this important fact, mainly because I abstracted away the schema validation from the publication creation):
Meteor.publish('somePub', function (args) {
pubSchema.validate(args) // throws on fail
const self = this
try {
// ... publication logic
catch (pubErr) {
self.error(pubErr)
}
})
So I thought this could not be the issue's source but here is the thing: Simple Schema is not a pure Meteor package but a NPM package and won't throw a Meteor.Error but a custom instance of Error, that actually has the same attributes (error, errorType, details) like a Meteor.Error, see this part of the source code of a validation context.
So in order to pass the correct information of a SimpleSchema validation error to the client you should
wrap it in a try/catch
add the isClientSafe flag to it
alternatively convert it to a Meteor.Error
Attach a custom Meteor.Error as sanitizedError property to it

Document Client Exception Incorrect Error Status Code

While testing DocumentDb stored procedures I intentionally created a document with a duplicate id so that I can observe the DocumentClientException. According to the documentation at http://azure.github.io/azure-documentdb-js-server/Collection.html#.ErrorCodes I was expecting the exception to have a 409 status code indicating Conflict.
The stored procedure code is as follows:
isAccepted = collection.createDocument(collectionLink,
duplicateIdDoc,
{ disableAutomaticIdGeneration: true },
function(err, createdDoc, options){
if (err) throw err; // Rollback
});
I do receive an exception but the error code is 400 (BadRequest). The message text indicates the correct problem. A resource with the specified id or name already exists.
"Message: {\"Errors\":[\"Encountered exception while executing function. Exception = Error: {\\"Errors\\":[\\"Resource with specified id or name already exists\\"]}\r\nStack trace: Error: {\\"Errors\\":[\\"Resource with specified id or name already exists\\"]}\n at Anonymous function (duplicateIdTest.js:56:26)\n at Anonymous function (duplicateIdTest.js:685:29)\"]}\r\nActivityId: 886230cf-8d49-433e-845f-8cc7c2ae486d, Request URI: /apps/514defcb-ac21-44e6-a8e0-c7b785523c6c/services/32782613-7101-4924-97b0-604052a6723b/partitions/be6c2ec8-130c-4596-90a2-b1807977dd0b/replicas/131240065159522367p"
Am I missing something? Thanks.
All errors thrown inside stored procedures are propagated as 400 (BadRequest). However, individual calls to the database like createDocument return the same error codes as the REST API.
For example, you can check the value of err.code === 409 inside your callback to validate that crateDocument failed due to a conflict. amd not something else.
err.code wouldn't work, Use err.number in your callback to handle known exception
Ex: err.number === 409 for conflict

Angular 2 http service. Get detailed error information

Executing Angular2 http call to the offline server doesn't provide much info in it's "error response" object I'm getting in the Observable's .catch(error) operator or subscription error delegate (they are both share the same info actually). But as you can see on the screen shot of the console there's actual error was displayed by zone.js somehow.
So, how can I get this specific error info (net::ERR_CONNECTION_REFUSED)?
Thanks.
Whenever server do not respond, response.status will be always equal to 0 (zero)
{
type: 3, //ResponseType.Error
status: 0, // problem connecting endpoint
}
Also note, when you are performing CORS request, but origin (url in browser) is not authorized (not in allowed list of host names configured in remote endpoint) the response would be similar to above, with exception to type attribute which will be equal to 4 = ResponseType.Opaque...
This means, connection was made, but for instance, OPTIONS request returned with headers which do not contain origin or HTTPS request was performed from HTTP origin.
You can handle the error messages so they are easier to read. This can definitely be expanded on too:
public Get() {
return this.http.get(this.URL).map(this.extractData)
.catch(this.handleError);
}
public extractData(res: Response) {
let body = res.json();
return body || {};
}
public handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
Check out this part of the docs on error handling.
Without digging in the code, my expectation is that if the server is unreachable, then no response can be returned from the server. Therefore the Response object remains its initialized state.

Resources