Firebase Cloud Functions returns INTERNAL Error - javascript

In the below code, while I'm trying to insert data into firebase Firestore, the data gets inserted but on returning promise, it returns error as INTERNAL Error. Hera is the console logged Error
Error: INTERNAL
at new f (error.ts:66)
at y (error.ts:175)
at O.<anonymous> (service.ts:231)
at tslib.es6.js:100
at Object.next (tslib.es6.js:81)
at r (tslib.es6.js:71) "INTERNAL"
The Code in Cloud Functions (index.js)
exports.addNewBook = functions.https.onCall((data, context) => {
return admin.firestore().collection('books').add(data.book)
.then((doc) => { return doc })
.catch((error) => { return error });
});
The Client Function invoking the Cloud Function (Client Function)
const addNewBooks = (formData) => {
bookData = {
no: formData.bookNo.value,
name: formData.bookName.value,
author: formData.bookAuthor.value,
publisher: formData.bookPublisher.value,
librarian: formData.librarianName.value
}
console.log(bookData);
const addBooksToDb = firebase.functions().httpsCallable('addNewBook');
addBooksToDb({
book: bookData
})
.then(doc => {
console.log(doc, doc.id)
})
.catch(error => {
console.log(error, error.message)
});
}
$("#addBookModalForm").submit(function(e) {
e.preventDefault();
addNewBooks(this);
this.reset();
});
Error logged on Cloud Functions on console.log() in index.js
addNewBook
Unhandled error RangeError: Maximum call stack size exceeded
at isArrayLike (/srv/node_modules/lodash/lodash.js:11333:31)
at keys (/srv/node_modules/lodash/lodash.js:13307:14)
at /srv/node_modules/lodash/lodash.js:4900:21
at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/srv/node_modules/lodash/lodash.js:13400:7)
at encode (/srv/node_modules/firebase-functions/lib/providers/https.js:179:18)
at /srv/node_modules/lodash/lodash.js:13401:38
at /srv/node_modules/lodash/lodash.js:4905:15
at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/srv/node_modules/lodash/lodash.js:13400:7)
What is the reason for throwing an INTERNAL Error

The promise returned from add() probably rejected and generated an error. If you don't take care to send a specific, known response to the client, you could see an error on the client.
Since we can't see the exact inputs and outputs (you are just showing variables here), and the log output, we have no way of knowing exactly what happened, so you will have to debug this to figure out what went wrong.

Related

nodejs app crash on openai dall-e 2 api rejected request

I'm surely dumb, but I'm not able to figure out how to handle openai api rejected requests
( for the context, dall-e 2 is an image generator )
when user tries to generate forbidden images, my nodejs app just exits
async function start(arg) {
try{
// generate image
const response = openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
});
// on success response
response.then(res =>{
console.log("ok");
})
response.catch(err =>{
console.log(err);
});
} catch(e){
console.log(e);
}
}
it gives me something like that on the exit :
data: {
error: {
code: null,
message: 'Your request was rejected as a result of our safety system. Your prompt may contain text that is not allowed by our safety system.',
param: null,
type: 'invalid_request_error'
}
}
tried using response.catch and try catch without success, the app just exits everytime
I at least want to ignore this error in the first place
in a second hand, I would like to console.log the given message (data.error.message)
I don't know what to do to by honest, don't even understand why try catch isn't working
With the details given, my guess would be that the Promise returned by getImages is being rejected. You could debug this a bit by adding some additional logs into your .catch callback and catch statement.
How to do this really depends on what you're trying to do with this api, the code as it's currently written would log something and exit no matter what happens.
There's a couple ways to handle this
Use your .catch to handle the error. Utilizing promise chainability you can get something like this
openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
user: msg.author.id,
})
.catch((e) => {
if (e.data.error.message.includes('safety system')) {
return 'something'
}
console.error(e)
})
If you need the response object, the asnwer might be different. Looks like the openai package is built on axios and you can pass axios options into it. See https://axios-http.com/docs/handling_errors and the Request Options section of https://npmjs.com/package/openai
EDIT
I found my solution thanks to #JacksonChristoffersen
Basically I was getting http status 400
I just added request options from axios to validate http status smaller than 500
Here's the solution:
async function start(arg) {
try{
// generate image
const response = openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
},{
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
}
});
// on success response
response.then(res =>{
console.log("ok");
})
response.catch(err =>{
console.log(err);
});
} catch(e){
console.log(e);
}
}

Twilio Error - ConnectionError (31005): Error sent from gateway in HANGUP

Trying to connect two users to the same conference call, but getting this error first:
error: ConnectionError: ConnectionError (53000): Raised whenever a signaling connection error occurs that is not covered by a more specific error code.
and then getting this error:
Received an error from the gateway: ConnectionError: ConnectionError (31005): Error sent from gateway in HANGUP
at ConnectionError.TwilioError [as constructor]
In my TwiML error logs this is what I see:
TwiML response body too large
For full context, users are first matched together, this happens in the 'waiting room' component:
function createTwilioConference(username, matchedUser){
const pairedUsers ={}
pairedUsers['roomName'] = sortUsersAlphabetically([username,matchedUser]).join('')
pairedUsers['participantLabel'] = sortUsersAlphabetically([username,matchedUser])
pairedUsers['currUser'] = username
pairedUsers['matchedUser'] = matchedUser
axios.post(`${profileURL}voice_chat/rooms`,pairedUsers)
.then(res =>{
console.log('twilio call created', res.data)
})
}
This function is wrapped in a useEffect that has an empty dependency array. Both users who have been matched together receive an XML object creating a twilio conference call
<?xml version="1.0" encoding="UTF-8"?><Response><Dial><Conference participantLabel="['emmanuelS21', 'testingUser']" startConferenceOnEnter="true">emmanuelS21testingUser</Conference></Dial></Response>
The conference room name is the same for both users (sort their names alphabetically and concatenating them to create the room name).
Both users are then redirected to the pair programming session where the call is initiated:
useEffect(() => {
console.log('!!!*** how many times is twilio being called ***!!!')
const params = {
roomName: roomName, participantLabel: user.username
};
if (!call) {
const callPromise = device.connect({ params });
callPromise.then((call) => {
console.log(' ***what is call', call)
setCall(call);
});
}
if (!participants.current.includes(user.username)) {
participants.current.push(user.username);
}
}, []);
I'm not sure how big an issue this is, but I noticed that my useEffect is being called four times

Getting cal cancelled error in firebase cloud functions

Firebase cloud functions logs "Error: 1 CANCELLED: Call cancelled" sometimes. am trying to send the push notifications one day before the timestamp, everything works till getting the fcm tokens but not able to send notification here is my code.
const NotificationLive_dayBefore = async () => {
try {
const path = models.payments.firebasePath;
let imageURL = null;
let tokens = [];
let subscribedUsers = await getSubscribedUsers().catch(e => { console.log(e) });
if (subscribedUsers && subscribedUsers.length > 0) {
for(const subscriber of subscribedUsers){
const userDoc = db
.collection('Payments').doc('v1').collection('users')
.doc(subscriber)
.collection('subscriptions').where('deleted_at', '==', null)
.get() // <------------here is the error according to logs
.then(async (snapshot) => {
if (!snapshot.empty) {
console.log('snapshot.empty', snapshot.empty);
for(const doc of snapshot.docs ){
// let friend_doc_id = doc.data().friend_doc_id
console.log("Friend id", doc.id);
if (doc.exists) {
let oneDay = new Date().getTime() + (24 * 60 * 60 * 1000);
let oneDayMinus1 = new Date().getTime() + (23 * 60 * 60 * 1000);
console.log(oneDayMinus1);
console.log(oneDay);
try {
let liveLesson = await db
.collection('Lessons').doc('v1').collection('friends')
.doc(doc.id)
.collection('live')
.where('start_time', '>', new Date(oneDayMinus1))
.where('start_time', '<', new Date(oneDay))
.where('deleted_at', '==', null)
.get();
for( const liveSnap of liveLesson.docs){
console.log("liveSnapid", '=>', liveSnap.data());
console.log('Private lesson exists', liveSnap.exists);
if (liveSnap.exists) {
// time is equal send notification
console.log("Subscriber ID", subscriber);
const Users = db
.collection(models.notification.firebasePath)
.where('deleted_at', '==', null)
.where('__name__', '==', subscriber)
.get()
.then(async (UserSnapshot) => {
for( const userdoc of UserSnapshot.docs){
const userdocument = userdoc.data();
if (userdocument.fcm_token) {
tokens = userdocument.fcm_token;
}
console.log('tokens',tokens);
if (tokens.length>0) {
try {
let live_lessons_images = await db
.collection('Accounts').doc('v1').collection('friends')
.doc(doc.id)
.get();
if (!live_lessons_images.data().image_url) {
imageURL = null;
console.log("Image not found");
} else {
imageURL = live_lessons_images.data().image_url;
}
} catch (error) {
console.log('That did not go well.', error)
}
console.log("notification sent live lesson 24 hr before");
await sendNotificationNew(
"test",
test notification,
imageURL,
tokens
).catch(error => { console.error("promise 1", error) });; //send notification to users as a remainder for live lesson before one day
}
}
}).catch(error => { console.error("promise 1", error) });
}
}
} catch (error) {
console.log('That did not go well.', error)
}
} else {
console.log("friend_doc_id is not present");
}
}
}
}).catch(error => { console.error("promise error", error) });
} //end foreach of subscribed user
}
return Promise.all('success');
}
catch (err) {
// Handle error here
// This will return error from api
console.log("Exceptions: ", err);
}}
and my sendNotificationNew function is
const sendNotificationNew = async (title, body, image, tokens) => {
console.log("title", title);
if (tokens.length > 0) {
if(tokens.length>1){
tokens = tokens[tokens.length-1];
}
try {
let message = {
notification: {
title: title,
body: body
},
token: tokens
};
if (image) {
message.notification.image = image;
}
admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
console.log('Error sending message:', tokens);
});
} catch (err) {
console.log(err);
}
} else {
console.log("Token not available");
}
};
i was able to see the logs printing "title" of the notification, but not "Successfully sent message" or "Error sending message:".
Error message i got
Error: 1 CANCELLED: Call cancelled
at Object.callErrorFromStatus (/workspace/node_modules/#grpc/grpc-js/build/src/call.js:31)
at Object.onReceiveStatus (/workspace/node_modules/#grpc/grpc-js/build/src/client.js:327)
at Object.onReceiveStatus (/workspace/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:299)
at (/workspace/node_modules/#grpc/grpc-js/build/src/call-stream.js:145)
at processTicksAndRejections (internal/process/task_queues.js:79)
And this
Error: 9 FAILED_PRECONDITION: The requested snapshot version is too old.
at Object.callErrorFromStatus (/workspace/node_modules/#grpc/grpc-js/build/src/call.js:31)
at Object.onReceiveStatus (/workspace/node_modules/#grpc/grpc-js/build/src/client.js:327)
at Object.onReceiveStatus (/workspace/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:299)
at (/workspace/node_modules/#grpc/grpc-js/build/src/call-stream.js:145)
at processTicksAndRejections (internal/process/task_queues.js:79)
3rd Edit: Finally I've found the solution to this problem. A same error occurred in 2 cloud functions and I solved both of them by following the same process.
I'm not deleting the previous wrong answers, which didn't work for me, so that you also could know what won't work.
This error occurs because the Firestore has hit a limit.
I was trying to do lots of writes and updates in Firestore in parallel.
Example: Here all the functions are called all together. This is very fast as all the tasks are done in parallel. And recommended by Firebase.
But this might hit a limit in firestore and give error.
exports.botsCompletingLectures = functions.region('asia-south1')
.database.ref('triggerCloudFunctions/botsCompletingLectures')
.onUpdate(async(change, context)=>{
const promises = [];
promises.push(doSomeTaskInFirestore());
promises.push(doAnotherTaskInFirestore());
promises.push(doSomeMoreTaskInFirestore());
function doSomeTaskInFirestore(){
//Write to lots of documents in a collection
}
async function doAnotherTaskInFirestore(){
//Update lots of documents in firestore
}
async function doSomeMoreTaskInFirestore(){
//Do more tasks in firestore
}
return Promise.all(promises);
});
Solution: Here only one task will execute at a time and so it will take little more time. But will not give any error.
exports.botsCompletingLectures = functions.region('asia-south1')
.database.ref('triggerCloudFunctions/botsCompletingLectures')
.onUpdate(async(change, context)=>{
await doSomeTaskInFirestore()
await doAnotherTaskInFirestore()
return doSomeMoreTaskInFirestore()
function doSomeTaskInFirestore(){
//Write to lots of documents in a collection
}
async function doAnotherTaskInFirestore(){
//Update lots of documents in firestore
}
async function doSomeMoreTaskInFirestore(){
//Do more tasks in firestore
}
});
2nd Edit: The Cloud Function worked well for 4-5 days and then started giving errors again.
So this time I've given up on trying to fix it and instead enabled Retry on failure in Cloud Functions.
In my case as the Cloud Function is running correctly for some days and gives error on other days, due to some temperory problems, like network issue or cold start, so I can enable it here.
We should not enable it, if the error is permanent for eg a Bug in the code, else the function will keep on retrying for 7 days.
You can learn about Enabling Retry in Cloud Functions from this video.
https://www.youtube.com/watch?v=Pwsy8XR7HNE
1st Edit: The error appeared again the next day
So after reading and searching about it, I found out this problem occurs because of Cold Starting of a function after a long time and some Network problem and memory leak and most of the people (including me), who are getting this error, are getting it in PubSub Cloud Function and while doing some tasks in Firestore.
So I used a workaround. I don't know if it is recommended or not, but I'm tired of these errors, so I just did it.
I created a PubSub Cloud Function that updates a field value in Realtime Database. And this update in the field will trigger another function, that will do the task in firestore.
exports.triggerTheMainFunction = functions.pubsub.schedule('40 11 * * *').onRun(async(context)=> {
return admin.database().ref()
.child('triggerOtherFunction')
.child('doSomeTaskInFirestore')
.set(admin.database.ServerValue.increment(1))
.catch((error)=>{
console.log('Error incrementing the value', error);
});
});
And converted the Actual Function for Firestore from PubSub to Event Triggered. And since then I'm not getting any errors.
exports.doSomeTaskInCloudFirestore = functions
.database.ref('triggerOtherFunction/doSomeTaskInFirestore')
.onUpdate(async(change, context)=>{
//Do the task that was needed to be done in firestore.
});
If I get any errors in future, then I'll update this answer.
First Answer
I also got a similar error. I don't know what was causing the problem. But I solved it by installing the latest version.
So first I saved a copy of index.js on desktop and reinstalled everything.
I was using NodeJS 14 version. So I uninstalled it from control panel and downloaded the nodeJS 16 version from the nodejs website. And installed it.
ran in terminal.
npm install -g npm
then
npm install npm#latest -g
Then
firebase init
then
npm install -g firebase-tools
And then redeployed the same cloud function, without making any changes. And test run the function. And the error disappeared.
I resolved this issue by adding indexes in the firestore and proper catch blocks to all the promises to avoid unhandled rejection errors.

I've got different behavior for object assign on localhost vs Server

Why the Object.assign works fine on Localhost but on server it does not ?
My vue app is hosted on S3 and everything works fine besides the Object.assign.
The remote api is being called properly and the update is ok, but the object is not being assigned and I got an empty error in the catch.
log for console.log(JSON.stringify(e)) is just {}.
axios
.put(this.url + "/client/" + item.id, {
name: item.name,
contactName: item.contactName,
phoneNumber: item.phoneNumber,
email: item.email,
})
.then((response) => {
Object.assign(this.client[this.editedIndex], item);
})
.catch((e) => {
console.log(JSON.stringify(e));
this.dialogError = true;
});
},
I have tried change the object assign like this Object.assign({}, this.client[this.editedIndex], item);, but I got any unexpected behavior.
The error you get is most likely caused by an empty value of this.client[this.editedIndex]. Take a look on the below example:
(new Promise((resolve) => { resolve(); }))
.then(() => {
console.log('then');
Object.assign(undefined, {a: 1});
})
.catch((e) => {
console.error('error', JSON.stringify(e))
});
prints:
then
error {}
Replacing undefined by null gives similar results. Therefore I would assume that there is no value at your this.client at this.editedIndex key.
In error logging you should avoid using JSON.stringify() with Error instances, as JSON.stringify does not know how to handle it:
> JSON.stringify(new Error('message'))
'{}'
You are losing all the information - like message, stack etc.

API Endpoint URL

Basically, the weather API; Apixu changed everything to weatherstack recently, including their endpoints and I need help updating my twitter weather bot.
I did go through the documentation, changed to axios but I keep getting the "Cannot Read Property error"
My Old API Setup
const Twit = require('twit');
const config = require('./config');
const rp = require('request-promise-native');
async function setup(location) {
const options = {
url: "http://api.apixu.com/v1/current.json",
qs: {
key: API_KEY,
q: location
},
json: true
};
let result = await rp(options);
let condition = result.current.condition.text;
let tweetText = `The condition in ${location} is currently ${condition}!`;
console.log("TWEETING : ", tweetText);
sendTweet(tweetText)
}
According to their documentation, this is how it's supposed to be but I keep getting undefined errors.
const params = {
access_key: 'YOUR_ACCESS_KEY',
query: 'New York'
}
axios.get('https://api.weatherstack.com/current', {params})
.then(response => {
const apiResponse = response.data;
console.log(`Current temperature in ${apiResponse.location.name} is ${apiResponse.current.temperature}℃`);
}).catch(error => {
console.log(error);
});
The new Base URL: The new API requests start out with :
http://api.weatherstack.com/
documentation : https://weatherstack.com/quickstart
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'c
ondition' of undefined
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This
error originated either by throwing inside of an async function without a catch
block, or by rejecting a promise which was not handled with .catch(). (rejection
id: 1)
I would check the response.data.error object, if something goes wrong this will be populated. Funnily enough the http status code is still 200 for some error conditions.
axios.get('https://api.weatherstack.com/current', {params})
.then(response => {
if (!response.data.error) {
const apiResponse = response.data;
console.log(`Current temperature in ${apiResponse.location.name} is ${apiResponse.current.temperature}℃`);
} else {
console.log(`Response error: code: ${response.data.error.code}, info: ${response.data.error.info}`)
}
}).catch(error => {
console.error("An error occurred: ", error);
}
);
Using the free tier, I'm getting the following error with this request:
Response error: code: 105, info: Access Restricted - Your current Subscription Plan does not support HTTPS Encryption.
This is easily worked around by changing to http only (This will be less secure!):
axios.get('http://api.weatherstack.com/current', {params})
.then(response => {
if (!response.data.error) {
const apiResponse = response.data;
console.log(`Current temperature in ${apiResponse.location.name} is ${apiResponse.current.temperature}℃`);
} else {
console.log(`Response error: code: ${response.data.error.code}, info: ${response.data.error.info}`)
}
}).catch(error => {
console.error("An error occurred: ", error);
}
);
If you are using free version you need to use 'http' to work, i guess if you want to use 'https' it is premiun that you need to buy
Here is the simple example that i have used
http://api.weatherstack.com/current?access_key=0a82bdc4c6628b5f968dd500d30a8857&query=19.0760,-72.8777

Categories

Resources