Throwing newUserError in getData() function - google-apps-script

I am currently building a data connector but would like to throw and error out to the user if the date range they have provided is not supported by my API endpoint (we don't have data for more than 90 days). I looked through the documentation and found this: https://developers.google.com/datastudio/connector/error-handling#user-facing-errors
And copied the code example exactly and tried to run it but my project still isn't showing the error dialog box back to the user.
I've also taken a look at how other people implement this in this repository (https://github.com/googledatastudio/community-connectors) but still can't see an issue with what I wrote.
function getData(request) {
try {
var dataSchema = getDataSchema(request);
var data = lookupRequestData(request, dataSchema);
} catch (e) {
console.log('pre throw');
// throw Error('some error!');
cc.newUserError()
.setDebugText('Error fetching data from API. Exception details: ' + e)
.setText('There was an error communicating with the service. Try again later, or file an issue if this error persists.')
.throwException();
console.log('post throw');
}
return {
schema: dataSchema,
rows: data
};
}
I can see both the pre throw and post throw strings in my log but there is still no error message being displayed. Just wondering if someone might be able to offer a bit of advice for other things to try.
Thanks

Related

Cloud Functions for Firebase Could not handle the request after a successful request

TLDR: After writing a JSON (successfully) to my Firestore, the next request will give me Internal Server Error (500). I have a suspicion that the problem is that inserting is not yet complete.
So basically, I have this code:
const jsonToDb = express();
exports.jsondb = functions.region('europe-west1').https.onRequest(jsonToDb);
jsonToDb.post('', (req, res) => {
let doc;
try {
doc = JSON.parse(req.body);
} catch(error) {
res.status(400).send(error.toString()).end();
return;
}
myDbFuncs.saveMyDoc(doc);
res.status(201).send("OK").end();
}
The database functions are in another JS file.
module.exports.saveMyDoc = function (myDoc) {
let newDoc = db.collection('insertedDocs').doc(new Date().toISOString());
newDoc.set(myDoc).then().catch();
return;
};
So I have several theories, maybe one of them is not wrong, but please help me with this. (Also if I made some mistakes in this little snippet, just tell me.)
Reproduction:
I send the first request => everything is OK, Json in the database.
I send a second request after the first request give me OK status => it does not do anything for a few secs, then 500: Internal Server Error.
Logs: Function execution took 4345 ms, finished with status: 'connection error'.
I just don't understand. Let's imagine I'm using this as an API, several requests simultaneously. Can't it handle? (I suppose it can handle, just I do something stupid.) Deliberately, I'm sending the second request after the first has finished and this occurs.
Should I make the saveMyDoc async?
saveMyDoc isn't returning a promise that resolves when all the async work is complete. If you lose track of a promise, Cloud Functions will shut down the work and clean up before the work is complete, making it look like it simply doesn't work. You should only send a response from an HTTP type function after all the work is fully complete.
Minimally, it should look more like this:
module.exports.saveMyDoc = function (myDoc) {
let newDoc = db.collection('insertedDocs').doc(new Date().toISOString());
return newDoc.set(myDoc);
};
Then you would use the promise in your main function:
myDbFuncs.saveMyDoc(doc).then(() => {
res.status(201).send("OK").end();
}
See how the response is only sent after the data is saved.
Read more about async programming in Cloud Functions in the documentation. Also watch this video series that talks about working with promises in Cloud Functions.

How can I make Feathers (Express-based API Framework) Return Error Responses

I've read the Feathers book, so I know that to create an error response I simply instantiate the appropriate feathers-errors class:
import {BadRequest} from 'feathers-errors';
const errorResponse = new BadRequest(`foo`, `bar`);
However, I'm having difficulty returning that error response to the user. Even when I create an endpoint that does nothing but return an error response ...
class SomeService {
create(data) {
return new BadRequest(`foo`, `bar`);
}
}
it doesn't work: instead of getting an error response, I get no response, and inside the Chrome debugger I can see that the response is pending (until it eventually times out and becomes an ERR_EMPTY_RESPONSE).
I tried reading about Express error handling, and in the examples I saw people used next to wrap the the response. However, next comes from the error handler, and I'm not sure where in my Feathers code I can get that next function.
If anyone could help explain (using next or not) how I can return a complete, not pending, error response, I would greatly appreciate it.
Your services have to return a promise. If your code is not asynchronous you can turn it into a promise with Promise.resolve and Promise.reject:
class SomeService {
create(data) {
return Promise.reject(new BadRequest(`foo`, `bar`));
}
}
Also make sure you registered the Express error handler to get nicely formatted errors:
const errorHandler = require('feathers-errors/handler');
// Last in the chain
app.use(errorHandler);
There is also more information in the error handling chapter.

Uncaught SyntaxError: Unexpected token B on live but not local server

So i am making some ajax post and it seems to work fine on the localhost, but when I publish it to ec2 server on amazon, I get Uncaught SyntaxError: Unexpected token B. Which seems to point to JSON parsing failure. Exact same database, same browser, and same methods being called. Why would it work on local and not on the server.
$.ajax({
url: '#Url.Action("Action")',
type: "POST",
data: ko.toJSON(viewModel),
dataType: "json",
contentType: "application/json; charset:utf-8",
success: function (result) {
},
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
for (var key in errorData)
{
errorMessages.push(errorData[key]);
}
toastr.error(errorMessages.join("<br />"), 'Uh oh');
}
});
Here is the basic layout on the server side:
[HttpPost]
public JsonResult Action(ViewModel model)
{
try
{
Response.StatusCode = (int)HttpStatusCode.OK;
return Json("Successfull");
}
catch (Exception ex)
{
logger.Log(LogLevel.Error, string.Format("{0} \n {1}", ex.Message, ex.StackTrace));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
errors.Add(ex.Message);
return Json(errors);
}
}
Within the try statement, I do a couple of queries to the database and post some calculations on Authorize.Net (https://api.authorize.net/soap/v1/Service.asmx)
If there are any error with Authorize.net web service calls then I return errors like this:
if (profile.resultCode == MessageTypeEnum.Error)
{
logger.Log(LogLevel.Error, string.Join(",", profile.messages.Select(x => x.text)));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
profile.messages.ToList().ForEach(x => errors.Add(x.text));
db.SaveChanges();
return Json(errors);
}
This error that I am logging:
A public action method 'AddPromoCode' was not found on controller 'Flazingo.Controllers.PositionController'. at
System.Web.Mvc.Controller.HandleUnknownAction(String actionName) at
System.Web.Mvc.Controller.ExecuteCore() at
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) at
System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.b__5() at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.b__0() at
System.Web.Mvc.MvcHandler.<>c__DisplayClasse.b__d() at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
completedSynchronously)
You have another post at can't find action only on live server, works fine in local server, so I'm guessing that this post is specifically related to the javascript pieces, not the server-side pieces.
It sounds like something bad happens on the server, the server sends back some type of error, and the your error handler (in javascript) dies when trying to handle that response.
I get Uncaught SyntaxError: Unexpected token B. Which seems to point
to JSON parsing failure.
That sounds quite reasonable. Let's look at the code:
.ajax({
...
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
...
},
...
});
I would highly recommend taking a look at what xhr.responseText is. My guess it that it does not contain valid JSON, so the parseJSON method throws the 'Unexpected token B' error.
To look at this value, you could put console.log(xhr.responseText); or you could use a tool like the javascript debugger in your web browser or fiddler to see what is there.
My guess is that the server is sending back a string with something like There was an error on the server instead of JSON like you are expecting. I see that you have error handling built in - my guess is that there is an error within your error handling, and there is nothing to catch it. I would recommend doing debugging on the server side to see if there is an error somewhere that you are not expecting.
Perhaps profile.messages is something that can only be enumerated once, and when you try to do it again it throws an error. Or maybe DB.SaveChanges is throwing an error for some reason. Either of these would result in the logged message that you see with the behavior you see on the client side.
You are attempting to return a 400 response (Bad Request) with your own custom response content.
I think that IIS by default doesn't allow you to do this, and as CodeThug mentioned, may be replacing your custom JSON content with a server message.
But it appears that you can override this behaviour:
http://develoq.net/2011/returning-a-body-content-with-400-http-status-code/
<system.webServer>
<httpErrors existingResponse="PassThrough"></httpErrors>
</system.webServer>
I have received similar mysterious errors in the past when using ASP.NET script bundling on knockout and bootstrap, especially when including the already-minified versions in a bundle.
If you are running in DEBUG mode on localhost, then ASP.NET will not be minifying the javascript libraries. However, once you deploy, you are presumably no longer in DEBUG mode and now minifying/bundling the scripts. Sometimes the bundling/minification of these scripts can result in syntax errors similar to the one you posted.
If so, you may be able to load knockout from a CDN to avoid the need for bundling.
It seems JSON sending as the response from the server is badly generated
ex: if a value in the database is hi "my" friends
JSON file will be generated as text:"hi "my" friends"
so value for property text is badly generated.
double check values in production/development server for such values.
best practice is replace quotes with escape character
ex: text:"hi \"my\" friends"

Determining the location of a JSON parse error

I am creating a web application that allows a user to load data in JSON format. I am currently using the following function to read JSON files that I have saved on my local disk:
function retrieveJSON(url, callback)
{
// this is needed because FireFox tries to parse files as XML
$.ajaxSetup({ mimeType: "text/plain" });
// send out an AJAX request and return the result
$.getJSON(url, function(response) {
console.log("Data acquired successfully");
callback(response);
}).error(function(jqXHR, textStatus, errorThrown) {
console.log("Error...\n" + textStatus + "\n" + errorThrown);
});
}
This works perfectly for well-formed JSON data. However, for malformed data, the console log displays the following:
Error...
parsererror
SyntaxError: JSON.parse: unexpected character
This is almost entirely unhelpful because it does not tell me what the unexpected character is or what line number it can be found on. I could use a JSON validator to correct the file on my local disk, but this is not an option when the page is loading files from remote URLs on the web.
How can I obtain the location of any error? I would like to obtain the token if possible, but I need to obtain the line number at minimum. There is a project requirement to display an excerpt of the JSON code to the user and highlight the line where any error occurred.
I am currently using jQuery, but jQuery is not a project requirement, so if another API or JSON parser provides this functionality, I could use that instead.
Yeah, life with deadlines is never easy :).
This might help you out, after couple of hours googling around, I've found jsonlint on Git Hub. It looks promising, it includes a shell script that could be used on server side, and there is a browser JavaScript version of it that seems to be exactly what you were looking for.
Hope that this will help You.
i agree that life with deadlines is hard.
i'm incredibly happy that i don't have to live with deadlines, i'm my own boss.
so in search of a better solution to this problem, i came up with the following :
...
readConfig : function () {
jQuery.ajax({
type : 'GET',
url : 'config.json',
success : function (data, ts, xhr) {
var d = JSON.parse(data);
},
error : function (xhr, ajaxOptions, thrownError) {
if (typeof thrownError.message=='string') {
// ./config.json contains invalid data.
var
text = xhr.responseText,
pos = parseInt(thrownError.message.match(/position (\d+)/)[1]),
html = text.substr(0,pos)+'<span style="color:red;font-weight:bold;">__'+text.substr(pos,1)+'__</span>'+text.substr(pos+1, text.length-pos-1);
cm.install.displayErrorMsg('Could not read ./config.json :(<br/>'+thrownError+'<br/>'+html);
} else {
cm.install.displayErrorMsg('Error retrieving ./config.json<br/>HTTP error code : '+xhr.status);
};
}
});
},
...

How do I log an error with ELMAH when catching an error for proper JSON formatting in MVC 3

I have an ASP.NET MVC 3 application where I'm making an AJAX call and expecting a JSON result back. I'm using ELMAH to log errors. While testing I had an unexpected error. ELMAH logged the error, but my client side script doesn't because the result is not proper JSON now. If I handle all errors in the controller to return a proper JSON result, then the error doesn't get logged by ELMAH. I know I can call ELMAH specifically to log the error, but I rather like that I don't have to do that anywhere else.
Can anyone clarify the 'proper' way to handle this scenario?
for example
try
{
//service.dosomethingwitherror();
return new JsonResult { Data = new { result = true, message = "Success." } };
}
catch (Exception ex)
{
return new JsonResult { Data = new { result = true, message = "Failed." } };
}
Since I'm 'handling' this, ELMAH doesn't log. If I don't handle this my client won't get JSON...
You can use the ErrorSignal class to log manually. This will perform all configured elmah operations (log, mail, tweet, etc).
ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
See http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Signaling_errors for more information.
If you really don't like adding that code to your controller, you could not catch the exception server side and handle the ajax error event in your javascript.