-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crashing await on upload with metadata #25732
Comments
Hi @jurijsk, it sounds like you had a frustrating debugging experience. Thank you for filing an issue so we can try to improve the experience. I'd like to better understand the trouble you are facing. It seems that Azure Functions is terminating the worker when your async function rejects, which I presume happens on the line What is confusing to me is the log ordering when compared to your code:
I don't understand how this ordering could occur given that In addition, something small that I noticed is you are missing an Since your experience may be specific to Azure Functions, I encourage you to also file feedback directly with that team: https://github.com/Azure/azure-functions#issues--feature-requests |
Hi @xirzec thank you for you reply. Its good you have someone looking at it with fresh set of eyes. I've changed the code sample to make it more explainable and adress some of your notes. Log aslo update. I comply to to To clarify the execution results in 500 - Internal Server Error, which should not happed taking into account that awaits are in
No, not quite. Crash happens on So the execution will not return to function code after Regarding the order of log messages, it can change from execution to execution, but since its all async requests under the hood probably. You can run the code here: https://textjoint-api.azurewebsites.net/blob and I encourage you to run the code in your function app in azure. Judging by the trace the exception originates from |
@jurijsk I looked into this a bit more and it seems that it has to do with Node's unhandled promise rejection behavior changing to If you attach a rejection handler to the first promise like firstPromise.catch(() => context.log("first Promise rejected")); You'll see log output like this:
This is because when you There are some ways to avoid this situation (outside of manually attaching handlers when kicking off a promise). The first way is to await promises as you kick them off: const result = await firstClient.upload(...)
// do something with result
const secondResult = await secondClient.upload(...) But clearly this isn't great for parallelism, so if you want to kick off both promises and wait for them at the same time you can do this: const firstPromise = firstClient.upload(...)
const secondPromise = secondClient.upload(...)
try {
const [result1, result2] = await Promise.all([firstPromise, secondPromise]);
// do something with results
} catch(error){
// one of the promises rejected!
// you can use Promise.allSettled if you don't want to reject when one promise rejects
} I hope this makes sense. It's too bad that Node doesn't actually include any log output that the throw is happening because of unhandled promise rejection when using the |
Hi @jurijsk. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue. |
All right, I think I learned something today. Thank you @xirzec! My mental model of what is going on under the hood with await/async is closer to reality now, but I should say it is still confusing. It is strange that you have to rely on callbacks, instead of kicking of something and dealing with the result later with try/catch.
I guess I have to create some kind of awaitable wrapper that will do .catch internally and return object with By the way, do you think the behavior can me changes with Thank you, once again. |
Happy to have helped!
It should be doable, though
I agree that there is more complexity than would be ideal and that Node's decision to throw on unhandled promise rejection is a bit questionable, but I have the concern that if we invented some new async pattern we would be introducing yet another abstraction that developers would have to understand and reason about how it interoperated with other promise-based contracts. The main struggle I think comes from the fact that const promise1 = doOperation();
const promise2 = doOtherOperation();
return promise2.then( () =>{
console.log("p2 success!");
}, () => {
console.log("p2 error!");
}).then(() => {
// now "await" promise1
return promise1.then(() => {
console.log("p1 success!");
}, () => {
console.log("p2 error!");
});
}); In the above code it's not unreasonable to expect the error handling for promise1 to occur sooner, and this is what the runtime does. Since the runtime can't know if you will eventually subscribe to the promise rejection and since promises capture any thrown error (including runtime ones like syntax errors!) people would have a terrible time understanding that their program failed because of some silently swallowed exception. Unfortunately, once you have the nice syntactic sugar of async/await, it makes it much harder to have intuition about if promises are being subscribed to since you don't actually attach the handlers yourself as they are instead magicked out of the aether by the runtime. If you look at how TypeScript codegens async/await on runtimes that do not support it, you'll see that it's actually a tiny state machine that uses generator functions.
It's possible this would help achieve what you wanted, though it does seem like there is a performance tradeoff with using them. |
Hi @jurijsk. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue. |
Hi @jurijsk, we're sending this friendly reminder because we haven't heard back from you in 7 days. We need more information about this issue to help address it. Please be sure to give us your input. If we don't hear back from you within 14 days of this comment the issue will be automatically closed. Thank you! |
Describe the bug
Node execution crashes on
await
ofblob.upload()
at the wrong time and the wrong place.If you have 2 blobs to upload and one of them had metadata with '-' in the key. Process crashes on
await
on any of the promises, sending you into pretty lengthy debugging you never planned.Error:
: RestError: The metadata specified is invalid. It has characters that are not permitted.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
async/await
, and it is not helping here.Log
Additional context
used npm packages
The text was updated successfully, but these errors were encountered: