I think its working now
Good to hear. What was the issue?
Iām building an API / app based off the pattern from this tutorial. So the code is not 100% the same, but the response-building, serverless setup, etc is effectively identical. Since itās related to the Serverless setup and API responses, this chapter feels most relevant to my issue.
Iāve been running into an issue, described here at much more length, where the success responses work perfectly, but the error responses seem to get short-circuited by AWS, such that the returned error / object is not the one I build, but a generic NetworkError.
Iāve been digging around on this a ton, but havenāt gotten to the bottom of it. If I literally just change the 200 in a response to a 500:
A) The response hits a catch
on my frontend (good), and
B) The error
object passed to the promise catch
is just a NetworkError
, with none of the information from my constructed response.
Have others run into this? Iām really confused about what is causing it, and itās wasting a ton of time at this point.
Thanks,
Sasha
Hmmm I would need to look into this. But you are saying that the error is just wrapped on the frontend correct? As in, if you checked the HTTP request, the response should show your Lambda function is returning?
Hi Jayair ā thanks for responding!
Not sure I understand what you mean by āwrapped on the frontendā, or what you mean by checking the HTTP request. Iām definitely getting successful responses to the frontend, and the Lambda logs suggest that the Lambdaās getting hit on error, and executing properly (more below).
What appears to be going on is that my Lambda code is totally correct (how I know this below), but something is happening between Lambda execution and the Amplify.get()
promise resolution on the frontend. As far as I know, that means the issue is with one of:
- AWS API Gateway
- Amplify
- Middleware on my end
First, why I think my Lambda is executing correctly. Iāve added a ton of logging on AWS, and when I hit any endpoint on my serverless API, a buildResponse
function (I think modified based on one in in this tutorial) constructs a response object to return, and logs that object. The buildResponse
function is called on both success
and failure
, and logs the object as the last step before returning the object (directly to callback(null, thatObject)
).
It is, verifiably, the last step before the
END RequestId
log line in Cloudwatch, for both success and failure cases.
Consequently, I know that what is being logged is what is being returned. And what is logged is identical in structure between success and failure responses. Basically, this:
{
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
},
"body": "{}"
}
An error response here differs only in that the
statusCode
is greater than or equal to400
. If I make that single change, I run into the ābugā.
That bug is that the frontend appears to receive, as an error in the catch
rejection to the Amplify.get()
promise, a generic NetworkError
, with no reference to the actual object Iām constructing and returning from my Lambda. As in, the above body could be an object with error text, and that object (and body) would not be in the error
object returned on catch
.
I have created some middleware for my app. It toggles between online and āofflineā requests (fakes the request, so I can develop locally). But I tested this bug without the middleware (just ran a basic API.get().then(data => {}).catch(error => {})
chain), and when I hit an endpoint that returns one of the above-described constructed error objects, I just get a useless NetworkError
in that catch statement ā no middleware involved.
So I think I can cross that one off.
I also figured it might be the Lambda configuration, which is still my best guess, but Iām all set up for Lambda-Proxy integration. Hereās the basic structure of my serverless.yml file:
service: myservice
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"
provider:
name: aws
runtime: nodejs6.10
region: us-west-2
# Auto-deploy env from .env.yml file
environment: ${file(./.env.yml):${opt:stage}}
profile: myprofile
plugins:
- serverless-webpack
- serverless-offline
custom:
webpack:
webpackConfig: ./webpack.config.js
includeModules: true
functions:
projectsGetAll:
handler: handlers/projects/getAll.handler
events:
- http:
path: projects
method: get
cors: true
authorizer: aws_iam
Seems like a pretty vanilla Serverless setup, and I canāt see any important ways that it differs from that in this tutorial.
As I pointed out in the StackOverflow post I linked to above, the AWS console confirms that Iām set up for Lambda-Proxy. My API Gateway looks correctly configured.
So I think that leaves me with Amplify itself as the culprit here, but that also seems unlikely, because I havenāt seen a similar complaint from anyone.
So Iām super confused. I guess my biggest question is whether other people have seen this, so that I could research their setups/fixes. But do you have any sense of what this might be? Have you seen this issue before? Any code/configs you might need to see to know?
Thanks!
Sasha
Hey there! Thank you for the awesome tutorial. I really appreciate it! Iām stuck on this chapter and here is my error. My code is the exact same but I think I messed up the access permissions in one of the previous chapters but Iām not sure where my problem lies. What should I do?
I found the error. I did not successfully execute the serverless config credentials.
Thanks for reporting back.
Thanks for all the details. Here is what I see when I get a 500 error. This is what I see in the console.
Is that what you are seeing?
Wait a second. I just figured this one out!
I missed something really obvious, is the short of it. The error object that came back looked like this:
Error: Request failed with status code 500
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
And if I did error.message
, it would, sensibly, return Error: Request failed with status code 500
. But, if I tried error.response
, I got the constructed error message back, with the right error code. Weird, but fine, now that I know it.
Sorry to bother you, and hope thatās helpful for others!
Additional important note: Amplify has some weird behavior. Despite what their docs say, adding headers
in the options seems to cause misbehavior:
The above-mentioned response key only shows up when I donāt specify headers
in the request options. In other words, this request returns an error
with a response
key:
API.get('my-api', '/path')
But this one returns an error without the key:
API.get('my-api', '/path', { headers: { 'Content-Type': 'application/json' } })
Very weird, but true, at least for me. Even other options are fine, but the headers option seems to mess things up.
Thanks for reporting back. Glad you figured it out.
See if this helps you with the headers.
https://aws-amplify.github.io/amplify-js/media/api_guide#custom-request-headers
Hi there, Iām getting a very interesting error. So I had this whole thing up and running flawlessly. I added a few methods to my back end, but now my get, list, delete, and update methods work, however my API.post call is no longer working. In both the cli āserverless invoke local --function createā and in the lambda test console I get:
{
"errorMessage": "Unexpected token u in JSON at position 0",
"errorType": "SyntaxError"
}
even when I hard code my values to take in strings. Any ideas? Thanks!
Thatās usually because serverless-webpack
isnāt transpiling things correctly. Is your webpack.config.js
similar to the one in the guide?
I think I have the same problem with @ azimshaik.
serverless invoke local --function create --path mocks/create-event.json
Anything didnāt show up after running this invoke this.Could anyone give me any ideas for me to solve that problem ??
I actually wrote all the same of every code on this tutorial.Should I change any place ??Like pool id ,arm id,and so onā¦
Hmmm there shouldnāt be anything to change. Does it not print anything at all?
Oh, I could get result. I actually have two cognito user pool on ohio and Virginia by mistake. So I deleted Ohio one ,and it worked.
Oh thatās good. Thanks for reporting back.
Hi, I just used this command
$ serverless invoke local --function create --path mocks/create-event.json
and got error
Cannot create property 'events' on string 'create.main'
I made sure that my create.js
code is exact copy of what has been listed on the tutorial but still no luck. any pointers?
āResourceNotFoundException: Requested resource not foundā
Hi guys, Iāve been following the tutorial, and i am stuck, read the q and a, and the error seems to be due to severless not being able to find my dynamo table (resource), iāve gone back and forth, trying to change the regions so it matches my dynamo āarn:aws:dynamodb:us-east-2:423925291108:table/notesā
what am i doing wrong?
here is the yml file
and here is the dynamo table overview
Table name | notes |
---|---|
Primary partition key | userId (String) |
Primary sort key | noteId (String) |
Point-in-time recovery | DISABLEDEnable |
Encryption | DISABLED |
Time to live attribute | DISABLEDManage TTL |
Table status | Active |
Creation date | October 22, 2018 at 8:32:06 PM UTC+1 |
UTC: October 22, 2018 at 7:32:06 PM UTC
Local: October 22, 2018 at 8:32:06 PM UTC+1
Region (Ohio): October 22, 2018 at 2:32:06 PM UTC-5|
- Provisioned read capacity units|5 (Auto Scaling Enabled)|
- Provisioned write capacity units|5 (Auto Scaling Enabled)|
- Last decrease time -
- Last increase time -
- Storage size (in bytes) 0 bytes
- Item count 0
- Region|US East (Ohio)
- Amazon Resource Name (ARN)|arn:aws:dynamodb:us-east-2:423925291108:table/notes
Edit
I changed my config file (region was not set)
so i set it to:
[default]
region = us-east-2
and when i run:
aws dynamodb list-tables
logs :
{ āTableNamesā: [ānotesā ] }
so the table does exist, but im stil getting:
āResourceNotFoundException: Requested resource not foundā