Google Assistant Smart Home may return error 500 when doing Request Sync - google-smart-home

I am doing Request Sync for my users because I implemented a new device type.
For some users it succeeds, but for some users I got errors with status 500 as a response of Request Sync like below.
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
I noticed the following rule about this error
If the error occurs in the Request Sync for a user, the same result will occur if I try the same thing for the same user immediately afterwards.
However, if I make a request to that user a day later, the request to the user may be successful.
I looked at the following document, but there is no description about the 500 status error.
https://developers.google.com/assistant/smarthome/develop/request-sync
Do you know why this is happening? Also, if you know the solution, please let me know.
Edited on April 22, 2021
The script is the following. It is written in NodeJS.
const smarthome = require('actions-on-google');
const app = smarthome.smarthome({
jwt: require('config.json')
});
const agentUserIds = ["xxxxx", "yyyyy"];
const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
const requestSync = async () => {
for (userId of agentUserIds) {
await app.requestSync(userId)
.then(() => {
console.log("Request sync success");
})
.catch(err => {
console.log("Request sync error");
console.error(err);
});
await sleep(1000);
}
};
requestSync();
As a result, I got the following output. It succeeds for some specific users and fails for some specific users.
Request sync error
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
Request sync success

Hi Can you check you are sending the correct API-Key in the Header, related to the users / agenuserId for which the Call is getting failed.

Related

Getting status 400 as an error instead of json response

I have a front-end connected to back-end, using http requests.
I'm experiencing this thing where if I return res.status(200) I get a response which I can send with that response a message. But when I'm sending res.status(400). I'm getting an red error on console rather than a parsable response.
app.post('/new', (req, res) => {
const { fullname, phone, country, img } = req.body
return res.status(200).json({
title: 'Ok, we got you!'
})
})
// If I'm changing that status to 400 I get that red error on console and I cannot parse from it anything (anything atleast that I want)
Yes, and that's the correct behaviour with HTTP requests. HTTP 400 Bad Request indicates an error rather then a successful response from your web server. So you need to catch the error thrown by the server with either a .catch() clause or a try/catch block in order to access the data returned on your client side. You're server code is absolutely fine. Just add the code below to your client side application.
Using .catch approach
axios.get('/foo')
.catch(function(error) {
console.log(error.response.data);
console.log(error.response.data.title); // your title
console.log(error.response.status);
console.log(error.response.headers);
});
Using try/catch approach
try {
const resp = await axios.get('/foo');
} catch (error) {
console.log(error.response.data);
console.log(error.response.data.title); // your title
console.log(error.response.status);
console.log(error.response.headers);
}
For more information visit this link

Error when sending POST request from React app to Rocket backend returns failure

I'm writing a simple web with Rocket as backend and React as frontend.
The code snippet looks like this for login page
#[post("/login", data = "<data>")]
pub fn login(
conn: DbConn,
mut cookies: Cookies<'_>,
data: Form<LoginForm>,
) -> Result<JsonValue, NotFound<String>> {
let valid_account = match Account::find_by_email(&*conn, data.email.as_str()) {
Ok(account) => {
if account.password == data.password {
account
} else {
return Err(NotFound("Incorrect email or password!".to_string()));
}
}
Err(_) => return Err(NotFound("Incorrect email or password!".to_string())),
};
cookies.add_private(
Cookie::build(AUTH_COOKIE, valid_account.id.to_string())
.same_site(rocket::http::SameSite::Strict)
.finish(),
);
Ok(json!({
"email": valid_account.email,
"name": valid_account.name,
}))
}
Code for main.rs
fn main() {
rocket::ignite()
.mount("/", routes![
account::login::login,
],
)
.register(catchers![errors::unauthorized])
.attach(rocket_cors::CorsOptions::default().to_cors().unwrap())
.manage(establish_connection())
.launch();
}
and code for React when trying to send the post request
export const postForm = async (
pathUrl: string,
postInfo: { [name: string]: any }
) => {
let axiosConfig = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
},
};
try {
const response = await axios.post(
baseUrl + pathUrl,
querystringify.stringify(postInfo),
axiosConfig
);
return response.data as CurrentUser;
} catch (err) {
console.log(err);
return Promise.reject(err.response);
}
};
The code works fine it I enter the correct email and password.
However, it cannot capture the error message if I enter the wrong credentials.
Rocket log are the same between successful login and failure login which are
OPTIONS /login:
=> Error: No matching routes for OPTIONS /login.
=> Warning: Responding with 404 Not Found catcher.
=> CORS Fairing: Turned missing route OPTIONS /login into an OPTIONS pre-flight request
=> Response succeeded.
POST /login application/x-www-form-urlencoded:
=> Matched: POST /login (login)
=> Outcome: Success
=> Response succeeded.
and the error log in browser I captured was Error: "Request failed with status code 404" which was not the expected error message hard coded inside post function.
I believe it has something to do with Option or preflight processed inside Rocket which maybe in the purpose of security. But how can I suppress the system error and let my code to take over?
I have read previous SO post like state undefined: while sending post request from react app and GitHub issues like https://github.com/SergioBenitez/Rocket/issues/25. And still cannot find answer for my problem.
Thanks in advance!
Apparently I made several mistakes here due to unfamiliar with Rocket and React.
List here in case someone made the similar mistakes.
The 404 status code is from the first code snippets Result<JsonValue, NotFound<String>>. So if we write the return type as Result<JsonValue, Unauthorized<String>>, it would return 401 as unauthorized user.
Second, axios only receives json type and cannot parse string (correct me if I'm wrong). So we need to change the return type in server to Result<JsonValue, Unauthorized<JsonValue>>.

Alexa skill is giving 'There was a problem with the requested skill's response', can we change this message to custom message?

I am new to Alexa skill, and I am developing an Alexa skill, in my case there are scenario when I don't want to wait for http response to back and if my lambda timeouts due to delay in response from Http can I give a custom message in place of 'There was a problem with the requested skill's response'. My code is :
'ProtectArmIntent': function() {
if(checkAccessToken(this.event.session.user.accessToken)){
var data = {
mode: HUB_MODE.ARM,
regId: "null"
}
callAPI("post", API_COMMANDS.HUB_MODE, data, this.event.session.user.accessToken)
.then((body) => {
if(body.response.status === "SUCCESS"){
this.emit(':tell', messages.ARM.SUCCESSFUL);
} else {
this.emit(':tell', messages.ARM.FAILED);
}
})
.catch((err) => {
this.emit('SessionEndedRequest');
//errorHandler.call(this, err, messages.ARM.FAILED);
});
} else {
this.emit('LinkAccount');
}
},
and alexa simulator request:
"request": {
"type": "SessionEndedRequest",
"requestId": "amzn1.echo-api.request.67e1612e-f8a4-43f5-ab28-175ba7d7941f",
"timestamp": "2019-11-13T21:13:11Z",
"locale": "en-GB",
"reason": "ERROR",
"error": {
"type": "INVALID_RESPONSE",
"message": "An exception occurred while dispatching the request to the skill."
}
}
I know the issue is because lambda timeout as delay in the HTTP response, so can I give some customize message like Your command is accepted and it will be executed in some time.
Please please help, Thanks in advance
Making your own timer function might help. Set your timer lower than the lambda timeout and send your response at the end of the timer which will of course not lead to a lambda timeout error.This answer might help.

How to hide console status error message while fetching in React js?

In my React app, I'm using fetch() to get data from my API, _callAPI() function gets domain parameter and call API if a website of the domain exists in my DB. If it exists, it returns the website's object, otherwise it returns 500. So, I can't figure out if the website exists until I use fetch(). The problem is that every time fetch() doesn't find anything, it throws the following:
container.jsx:25 GET
http://localhost:3000/boutiques/detail/?q=testdomain.com
500 (Internal Server Error)
When it doesn't doesn't find a lot of websites, the console log is packed with that error message. Is there a way to ignore that sort of message while fetching?
fetch()
_callApi = () => {
const { domain } = this.props;
return fetch(`/boutiques/detail/?q=${domain}`)
.then(response => {
if (response.status === 500) {
return 500;
}
return response.json();
})
.then(json => json)
.catch(err => console.log(err));
};
If you want to mute the browser error:
Unfortunately, this cannot be done, as this type of message in the
console is printed by chrome itself. Repressing this type of message
has been debated for years, but the consensus seems to be that this
message is desirable
Credits.
If you want to mute the Unhandled error in the console:
You can always mute the error on front-end, as follows:
.catch(err => { const mute = err })
But it would be better to notify somehow the user about the error and not doing such workarounds.
Also it would better your server to return an error message in the response and on the front-end side you will proceed it.
Looking into your case, it may be better the server to response with status code 400. Here are the HTTP error codes and their purpose:
4xx (Client Error): The request contains bad syntax or cannot be
fulfilled
5xx (Server Error): The server failed to fulfill an
apparently valid request

How to handle api errors using aws-amplify?

I'm currently trying to POST data to my aws lambda functions triggered by aws api-gateway using the aws-amplify react lib.
Here is the code :
API.post("snippets","snippets/", {
body: data,
}).then(response => response).catch(console.log(err))
In the main case, everything is OK.
But my lambda function is design to validate the input data and return a status code 400 with a returned payload looking like that :
{
"errors": [
{
"field": "title",
"message": "This field is required"
}
]
}
I would like to catch those errors in order to display them in the frontend but aws-amplify seems to have an undocumented behavior.
By default, status code 400 returned are throw with a default error message :
Error: Request failed with status code 400
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
Is there a way to get the returned payload instead of this magical error?
It turns out that under the hood, aws-amplifyuse Axios to make http calls.
When using Axios, you have to console.log(error.response): https://github.com/axios/axios/issues/960
Here is the fix I've made :
API.post("snippets","snippets/", {
body: data,
}).then(response => response).catch(error => console.log(error.response.data))
A Pull Request on the aws-amplify documentation is open : https://github.com/aws/aws-amplify/pull/633
I also faced the similar issues, It showed the default error message "Request failed with status code 400", instead of the message that is returned from API.
I logged the Error object and it did not show the response attribute in it. But we do have response attribute. I tried logging the Error.response and it did contain the response sent from the API.
Just figured out this by going through the 'Cancel API requests' Amplify docs.
From what I can see this is the contents of the error object returned by the API call:
Heres what I am doing to just print out the error, obviously you would do a lot more here but its a good start.
async uploadUser(state, payload) {
const promise = API.graphql({
query: createUser,
variables: { input: payload },
});
try {
await promise;
} catch (error) {
// Print out the actual error given back to us.
console.log(error.errors[0].message);
// If the error is because the request was cancelled we can confirm here.
if (API.isCancel(error)) {
// handle user cancellation logic.
console.log(error.message);
}
}
Hope that helps 😃

Resources