Internal Error to send FCM notification to web application - node.js

I'm developing an internal client for triggering firebase cloud messaging push notifications.
With android devices it works without problems. however, when I try to send a notification to a pwa I get the message: FirebaseMessagingError: An internal error has occurred. Please retry the request
This is the code of the function I'm developing:
import admin from '../classes/FirebaseNotification.js';
const priority = 'high';
class FormatNotificationAndroid {
static sendNotification = (data) => {
let registrationTokens = data.devices;
let message = {
notification: {
title: data.notification.title,
body: data.notification.message,
}
};
let options = {
priority: priority,
timeToLive: data.notification.time_to_live
};
console.log(registrationTokens);
console.log(message);
console.log(options);
admin.messaging().sendToDevice(registrationTokens, message, options)
.then(response => {
console.log(response.results);
})
.catch(error => {
console.log(error);
});
}
}
export default FormatNotificationAndroid;
The error trace:
error: FirebaseMessagingError: An internal error has occurred. Please retry the request.
at FirebaseMessagingError.fromServerError (C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\utils\error.js:254:16)
at C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:93:65
at Array.forEach (<anonymous>)
at mapRawResponseToDevicesResponse (C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:89:26)
at C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:344:24
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
errorInfo: [Object],
codePrefix: 'messaging'

Related

How to get/log/capture the errors from a graphql apollo client query

I am interfacing with a graphql backend using the #apollo/client.
The request i am making returns a 400 bad request and in the network tab i can see the json of the errors.
This is what i would like to log in my code but i am uanble to.
try {
const response = await GraphQLClient.query({
query: GET_PERSON,
variables: {
personId: id,
},
errorPolicy: "all",
});
console.log("response", response);
} catch (err) {
console.log("err", err);
}
When i execute the above it goees into the catch block and i do not have access to the errors object.
err Error: Response not successful: Received status code 400
at new ApolloError (index.ts:54)
at QueryManager.ts:1073
at both (asyncMap.ts:30)
at asyncMap.ts:19
at new Promise ()
at Object.then (asyncMap.ts:19)
at Object.error (asyncMap.ts:31)
at notifySubscription (module.js:137)
at onNotify (module.js:176)
at SubscriptionObserver.error (module.js:229)
at iteration.ts:13
at Array.forEach ()
at iterateObserversSafely (iteration.ts:13)
at Object.error (Concast.ts:185)
at notifySubscription (module.js:137)
at onNotify (module.js:176)
at SubscriptionObserver.error (module.js:229)
at createHttpLink.ts:203
graphqlservice
import { ApolloClient, InMemoryCache } from "#apollo/client";
import { Config } from "./../config";
const FRONTEND_API = `${Config.frontend_api}/graphql` || "";
export const GraphQLClient = new ApolloClient({
uri: FRONTEND_API,
cache: new InMemoryCache(),
}
To get the errors as a json response in the catch method.
console.log(err.networkError.result.errors);
Still very unsure why the response object has an error and errors property and i don't know when these are accessible, maybe someone else could shed some light on that.
export declare type ApolloQueryResult<T> = {
data: T;
errors?: ReadonlyArray<GraphQLError>;
error?: ApolloError;
loading: boolean;
networkStatus: NetworkStatus;
partial?: boolean;
};

discord.js bot crashes after trying to send a message in a channel it can't send messages

Well discord.js bot crashes after trying to send a message in a channel it sees but can't send messages
well I get a crash after that, how can I fix this? here is the error it shows it shows for other commands too
/home/pi/Desktop/floppa_gaming/node_modules/discord.js/src/rest/RequestHandler.js:298
throw new DiscordAPIError(data, res.status, request);
^
DiscordAPIError: Missing Permissions
at RequestHandler.execute (/home/pi/Desktop/floppa_gaming/node_modules/discord.js/src/rest/RequestHandler.js:298:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (/home/pi/Desktop/floppa_gaming/node_modules/discord.js/src/rest/RequestHandler.js:50:14)
at async TextChannel.send (/home/pi/Desktop/floppa_gaming/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js:171:15) {
method: 'post',
path: '/channels/785243249072930869/messages',
code: 50013,
httpStatus: 403,
requestData: {
json: {
content: 'You can use get help by saying "floppa help" in the chat :wink:',
tts: false,
nonce: undefined,
embeds: undefined,
components: undefined,
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: undefined,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined
},
files: []
}
}
and if anyobody wants to see my terrible code here it is
const { Client, Intents, MessageEmbed, Permissions } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES,] });
var fs = require('fs');
var files = fs.readdirSync('./floppa/');
client.on('ready', () => {
client.user.setStatus('invisible') //You can set idle, dnd or invisible
client.user.setActivity("use floppa to get a image!", { type: 'PLAYING' }) // PLAYING , LISTENING , WATCHING , STREAMING
console.log("on discord lol");
});
const { AutoPoster } = require('topgg-autoposter')
const poster = AutoPoster('token', client) // tells topgg amount of servers ur bot is in
// optional
poster.on('posted', (stats) => { // ran when succesfully posted
console.log(`Posted stats to Top.gg | ${stats.serverCount} servers`)
})
client.on('message', msg => {
if (msg.content === 'floppa')
{
imageNumber = files[Math.floor(Math.random()*files.length)]
msg.channel.send ( {files: ["./floppa/" + imageNumber]} )
}
// finds a random image in a folder
The error shown is: DiscordAPIError: Missing Permissions
This means that your bot does not have permission to send messages in that channel. To avoid your bot crashing when this happens, you need to do one of the following:
Catch the error:
msg.channel.send("stuff").catch((err) => {/* handle errors */});
Verify that your bot has the permissions to post before posting:
if (msg.guild && msg.channel.permissionsFor(msg.guild.me).has("SEND_MESSAGES"))) {
msg.channel.send("stuff");
}

Adding firebase firestore entry failed : 7 PERMISSION_DENIED

I'm trying to use a Firebase Cloud Function to create a document within the Firestore database from my Node js environment with Express js, but it fails with below error on the function logs.
Error: Process exited with code 16
at process.on.code (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:275:22)
at process.emit (events.js:198:13)
at process.EventEmitter.emit (domain.js:448:20)
at process.exit (internal/process/per_thread.js:168:15)
at Object.sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/logger.js:37:9)
at process.on.err (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:271:22)
at process.emit (events.js:198:13)
at process.EventEmitter.emit (domain.js:448:20)
at emitPromiseRejectionWarnings (internal/process/promises.js:140:18)
at process._tickCallback (internal/process/next_tick.js:69:34)
firebase.ts file :
import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions'
admin.initializeApp({
credential: admin.credential.cert({
privateKey: functions.config().private.key.replace(/\\n/g, '\n'),
projectId: functions.config().project.id,
clientEmail: functions.config().client.email
}),
databaseURL: 'https://app-id.firebaseio.com'
})
const db = admin.firestore()
export { admin, db }
controller.ts :
import { Response } from 'express'
import { db } from './config/firebase'
type EntryType = {
title: string,
text: string,
}
type Request = {
body: EntryType,
params: { entryId: string }
}
const addEntry = async (req: Request, res: Response) => {
const { title, text } = req.body
try {
const entry = db.collection('entries').doc()
const entryObject = {
id: entry.id,
title,
text,
}
await entry.set(entryObject).catch(error => {
return res.status(400).json({
status: 'error',
message: error.message
})
})
return res.status(200).json({
status: 'success',
message: 'entry added successfully',
data: entryObject
})
} catch(error) {
console.log(error);
return res.status(500).json(error.message)
}
}
Im receiving below response from this trigger :
{
"status": "error",
"message": "7 PERMISSION_DENIED: Invalid project number: 113102533737774060828"
}
Is this related to the Cloud Firestore rules in the Google cloud? Im fairly new to Google cloud functions.
Any suggestions would be appreciated.
This typically means that the credentials you're using are not for the project you're trying to use them on.
Check your functions.config().private.key to ensure it is indeed for the project you run this code on.

Error method sendAll() in nodejs using firebase-admin

I use firebase-admin for nodejs(version 7.3.0) for sending push
notifications. For 40k distinct messages sending with method sendAll often server received this error:
"Credential implementation provided to initializeApp() via the "credential"
property failed to fetch a valid Google OAuth2 access token with the
following error: "Error fetching access token: Error while making request:
socket hang up. Error code: ECONNRESET".
Sometimes it works well but not all the time.
var admin = require('firebase-admin');
serviceAccount = require('/path_json_adminsdk/yyyyyyyyyy.json');
var defaultApp = admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://api-project-yyyyyy'
});
var k = 42000;
var contorMessages = 0;
var messages = [];
for(var i=0;i <em><</em> k; i++){
//.......
contorMessages = contorMessages + 1;
var tmp = {
alert: body.alert,
payload: body.payload
};
//form the array to be sent
messages.push({
data: {"body": JSON.stringify(tmp)},
token: body.token
});
if(contorMessages == 100){
SEDispatcher.emit('sendMessageFirebaseMulticast',messages);
contorMessages = 0;
messages = [];
}
}
SEDispatcher.on('sendMessageFirebaseMulticast', function(messages){
var dryRun = true;
admin.messaging().sendAll(messages, dryRun)
.then(function(response) {
//console.log("response:",response);
//responses = response.responses;
//.......
})
.catch((error) => {
console.log(' +++ Error sending message:', error);
});
});
the error that occurs sometimes:
+++ Error sending message: { Error: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a
valid Google OAuth2 access token with the following error: "Error
fetching access token: Error while making request: socket hang up.
Error code: ECONNRESET".
at FirebaseAppError.Error (native)
at FirebaseAppError.FirebaseError [as constructor] (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:122:28)
at /opt/node/test/node_modules/firebase-admin/lib/firebase-app.js:121:23
at process._tickCallback (internal/process/next_tick.js:103:7) errorInfo: { code: 'app/invalid-credential',
message: 'Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2
access token with the following error: "Error fetching access token:
Error while making request: socket hang up. Error code: ECONNRESET".'
}, codePrefix: 'app' }
const messaging = getMessaging(defaultApp);
Need to be load
let serviceAccount = require('./google.json');
function messaging() {
const defaultApp = initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const messaging = getMessaging(defaultApp);
const topic = 'highScores';
const message = [
{
data: {
score: '850',
time: '2:45'
},
topic: topic
}
];
messaging
.sendAll(message, true)
.then(function (response) {
console.log('response:', response);
})
.catch((error) => {
console.log(' +++ Error sending message:', error);
});
}
Assuming that the JSON is the file that contains your private key that is generated when registering the project

GraphQL Error Handling with ApolloClient and Apollo-Server-Express

The onError function from apollo-link-error has a populated graphQLErrors Object, but when ApolloClient throws an error object, the graphQLErrors property contains an empty array. Further inspection reveals the graphql error message in error.networkError.result.errors.
How can one properly configure Apollo Client to return a populated graphQLErrors object?
Apollo Client Setup:
const {ApolloClient} = require('apollo-client')
const { ApolloLink } = require('apollo-link')
const {HttpLink} = require('apollo-link-http')
const {onError} = require('apollo-link-error')
const {InMemoryCache} = require('apollo-cache-inmemory')
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
})
const middleware = (req, ignored_res, next) => {
const client = new ApolloClient({
link: ApolloLink.from([errorLink, new HttpLink({ uri:'http://somegraphqlserver.com', fetch: require('node-fetch') })]),
cache: new InMemoryCache(),
})
req.GQLClient = client
return next()
}
module.exports = middleware
Calling apollo-server-express:
req.GQLClient
.query({
query: SOME_MALFORMED_QUERY,
})
.then((data) => {...})
.catch((error) => {
console.log('rawError', error)
console.log('error.networkError.result.errors', error.networkError.result.errors)
return next(error)
})
Console Results:
[GraphQL error]: Message: Cannot query field "blah" on type "CustomerList"., Location: [object Object], Path: undefined
[Network error]: Error: Response not successful: Received status code 400
rawError { Error: Network error: Response not successful: Received status code 400
at new ApolloError (/.../node_modules/apollo-client/bundle.umd.js:121:28)
at /.../node_modules/apollo-client/bundle.umd.js:1187:41
at /.../node_modules/apollo-client/bundle.umd.js:1620:17
at Array.forEach (<anonymous>)
at /.../node_modules/apollo-client/bundle.umd.js:1619:18
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (/.../node_modules/apollo-client/bundle.umd.js:1614:22)
at /.../node_modules/apollo-client/bundle.umd.js:1114:31
at process._tickCallback (internal/process/next_tick.js:178:7)
graphQLErrors: [],
networkError:
{ Error: Response not successful: Received status code 400
at throwServerError (/.../node_modules/apollo-link-http-common/lib/bundle.umd.js:33:21)
at /.../node_modules/apollo-link-http-common/lib/bundle.umd.js:58:17
at process._tickCallback (internal/process/next_tick.js:178:7)
response:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: [Object],
[Symbol(Response internals)]: [Object] },
statusCode: 400,
result: { errors: [Array] } },
message: 'Network error: Response not successful: Received status code 400',
extraInfo: undefined }
error.networkError.result.errors [ { message: 'Cannot query field "blah" on type "CustomerList".',
locations: [ [Object] ] } ]
library versions:
Server:
"apollo-server-express": "^1.3.2"
Client:
"apollo-cache-inmemory": "^1.1.12"
"apollo-client": "^2.2.8"
"apollo-link-error": "^1.0.9"
"apollo-link-http": "^1.5.4"
This is by design. From the docs:
graphQLErrors: An array of errors from the GraphQL endpoint
networkError: Any error during the link execution or server response,
that wasn't delivered as part of the errors field in the GraphQL result
In other words, if your query is malformed, you request a field that isn't valid (like in your example), or hit any other issue that results in status other than 200, the error will appear as part of the networkError property. On the other hand, if the request returns a 200, but the errors array inside the response is populated, those same errors will be returned as part of graphQLErrors.
If you want to see an example of graphQLErrors being populated, format your query correctly but have one of your resolvers throw an error as soon as it's called. As long as the query doesn't hit any other issues, you should see the same error pop up inside graphQLErrors.

Resources