Firebase Messaging fails sporadically with internal-error - firebase-cloud-messaging

I've been getting internal error quite a lot this week while sending messages to my iOS devices through the Node.js library (code is the same, same library version etc.)
It's hard to debug because sometimes it works. When I put a for loop to send 10 messages, my devices would get 3-4.
FirebaseMessagingError: Internal error encountered.
> at FirebaseMessagingError.FirebaseError [as constructor] (/node_modules/firebase-admin/lib/utils/error.js:42:28)
> at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/node_modules/firebase-admin/lib/utils/error.js:88:28)
> at new FirebaseMessagingError (/node_modules/firebase-admin/lib/utils/error.js:254:16)
> at Function.FirebaseMessagingError.fromServerError (/node_modules/firebase-admin/lib/utils/error.js:287:16)
> at Object.createFirebaseError (/node_modules/firebase-admin/lib/messaging/messaging-errors.js:34:47)
> at FirebaseMessagingRequestHandler.buildSendResponse (/node_modules/firebase-admin/lib/messaging/messaging-api-request.js:119:47)
> at /node_modules/firebase-admin/lib/messaging/messaging-api-request.js:94:30
> at Array.map (<anonymous>)
> at /node_modules/firebase-admin/lib/messaging/messaging-api-request.js:93:30
> at processTicksAndRejections (internal/process/task_queues.js:97:5) {
> errorInfo: {
> code: 'messaging/internal-error',
> message: 'Internal error encountered.'
> },
> codePrefix: 'messaging'
> }
I tried changing the auth key, but still getting errors.
Code is very simple
import * as admin from 'firebase-admin'
admin.initializeApp()
async function sendPushNotification(
tokens: string[],
title: string,
body: string
): Promise<admin.messaging.BatchResponse> {
console.log('sending %s to %d devices', body, tokens.length)
const message = {
notification: {
title: title,
body: body,
},
tokens: tokens,
apns: {
payload: {
aps: {
sound: 'default',
},
},
},
}
return admin.messaging().sendMulticast(message)
}

I have been having the same problem: node.js firebase admin SDK sending notifications to iOS occasionally fails with 500/ISE.
It seems specific to, or at least more common with, iOS as during Android development I never had this issue. I contacted Firebase support and here is what they said:
Internal Server Error are usually due to timeouts. Some minor hiccups can't be avoided that's why we recommend developers to implement exponential back-off retry mechanism. You can refer to this StackOverflow discussion for more information on retry-after and exponential back offs.
It seems like a good idea to build in some retry support on my side in any case. I haven't used it before but I like the look of the cockatiel module on npm. I'm planning on going with the retryWithBreaker example given at the start of their README, just with the backoff attempts and breaker set higher, maybe 5 and 20 respectively.

Related

WalletConnect disable infura error message

I am currently developing a dapp and I am integrating walletconnect.
I use this code for connecting:
const chainId = ContractService.getPreferredChainId();
const rpc = ContractService.getRpcAddress();
provider = new WalletConnectProvider({
infuraId: undefined,
rpc: {
[chainId]: rpc,
},
});
await provider.enable();
chainId is dynamically chosen based on if the app is in development mode or not. while in development it runs on chain id 97.
RPC is the same story, it just gets the binance smart chain RPC JSON provider.
Connecting works well, but I get the following error:
Any idea on how I can fix this without making an infura account? Or is that required..
I found out what the problem was.
make sure to add a chainId to the object like this:
new WalletConnectProvider({
infuraId: undefined,
rpc: {
1: "https://RPC_URL",
},
chainId: 1
});
Then it should work without issues, you can even omit the infuraId field

react-apollo Error: Network error: Unexpected token < in JSON at position 1

I want to send a request to this server via Apollo and get a query :
const client = new ApolloClient({
link: new HttpLink({
uri:'http://mfapat.com/graphql/mfaapp/'}),
cache: new InMemoryCache()
})
const FeedQuery = gql
query{
allFmr{
fmrId,
name,
studio,
bedRm1,
bedRm2,
bedRm3,
bedRm4
}
}
`
But I'm facing this error message:
Unhandled (in react-apollo:Apollo(FMRScreen)) Error: Network error: Unexpected token < in JSON at position 1
at new ApolloError (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:109336:32)
at ObservableQuery.currentResult (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:109447:28)
at GraphQL.dataForChild (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:103192:66)
at GraphQL.render (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:103243:37)
....
But I can easily open "http://mfapat.com/graphql/mfaapp/" in my browser and get a query. Does anyone know where the problem is?
Right now, Apollo treats everything sent from the server as JSON. However, if there is an error, then your server might be sending HTML to show a basic error page.
To see the error, open your dev tools, and look at the network tab. This shows an example 401 error:
As you can see, if you were to parse this as JSON you would stumble over the first character: < which is where our error message comes from.
Reading the specific error sent enables you to fix the bug.
To fix the general error, configure your server to send JSON on HTTP errors, not HTML code. This should allow Apollo to parse it and display a sensible error page.
EDIT: Also see this discussion - hopefully they will change the default Apollo behavior, or at least provide useful discussion.
Base on #eedrah answer, I managed to resolve this issue by using an error handler middleware to always return erros as JSONs, so that Apollo Client error link can parse the errors.
// On Apollo server
// Error handler
const errorHandler = (err, req, res, next) => {
if (res.headersSent) {
return next(err);
}
const { status } = err;
res.status(status).json(err);
};
app.use(errorHandler);

electron certificates network

I am trying to write a simple electron app to interface with a REST server. The server doesn't have the appropriate certificates. When I try to make a 'GET' request (using fetch()), I get the following error message:
Failed to load resource: net::ERR_BAD_SSL_CLIENT_AUTH_CERT
Fixing the certs is not currently an option. I tried to use the 'ignore-certificates-error' flag (see below). It seems like it should allow me to skip over this error, but it doesn't.
var electron = require('electron');
var app = electron.app
app.commandLine.appendSwitch('ignore-certificate-errors');
...
The result is the same error.
Questions:
I am correct in assuming this options is supposed to help here?
If so, any ideas what I am doing wrong?
Electron version: 1.2.8
Thanks!
You can update your version of electron and use this callback:
app.on('certificate-error', (event, webContents, link, error, certificate, callback) => {
if ('yourURL/api/'.indexOf(link) !== -1) {
// Verification logic.
event.preventDefault();
callback(true);
} else {
callback(false);
}
});
That you going do the fetch to your api with https.

Google Cloud Pub/Sub Node.js Sample: TypeError: Cannot read property 'on' of null

I'm using GCP and I want to use Cloud Pub/Sub. I got this error below when I tried Node.js sample. Does anyone knows how to fix it?
/private/tmp/pubsub/pubsubsample.js:26
subscription.on('error', onError);
^
TypeError: Cannot read property 'on' of null
at /private/tmp/pubsub/pubsubsample.js:26:15
at /private/tmp/pubsub/node_modules/gcloud/lib/pubsub/index.js:474:7
at Object.handleResp (/private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:113:3)
at /private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:422:12
at Request.onResponse [as _callback] (/private/tmp/pubsub/node_modules/gcloud/node_modules/retry-request/index.js:106:7)
at Request.self.callback (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:198:22)
at emitTwo (events.js:87:13)
at Request.emit (events.js:172:7)
at Request.<anonymous> (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:1035:10)
at emitOne (events.js:82:20)
https://github.com/GoogleCloudPlatform/gcloud-node
var gcloud = require('gcloud');
// Authenticating on a per-API-basis. You don't need to do this if you
// auth on a global basis (see Authentication section above).
var pubsub = gcloud.pubsub({
projectId: 'xxxxx',
keyFilename: 'xxx.json'
});
// Reference a topic that has been previously created.
var topic = pubsub.topic('info');
// Publish a message to the topic.
topic.publish({
data: 'New message!'
}, function(err) {});
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
... I'm using now PubSub but I'm thinking whether I can do same thing by using Google Cloud PubSub.
This post may be relevant. Node.js on Google Cloud Platform Pub/Sub tutorial worker is failing with "TypeError: Cannot call method 'on' of null"
Update 1
I changed to this code but same error was showed.
(error)
subscription.on('error', onError);
^
TypeError: Cannot read property 'on' of null
(code)
// Subscribe to the topic
topic.subscribe('new-subscription', function(err, subscription) {
if( err ) {
// something went wrong, react!
return;
}
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
Update 2
My expectation is this below.
execute "node pubsub.js"
I can see the sample message 'New message!'
When invoking topic.subscribe(), the method essentially invokes the pubsub.subscribe() method with a specific Topic instance as its context. This can be seen from the source code under Topic.prototype.subscribe.
Based on the PubSub index.js source code, PubSub.prototype.subscribe() issues a HTTP request to create a new subscription respecting the projects.subscriptions.create API format. If the response returns a 409 ALREADY_EXISTS error and you have not set the options.reuseExisting to true, the callback you provided will be invoked with the error and null as a subscription. According to the PubSub Nodejs documentation for topic.subscribe under options.reuseExisting, the default value if not specified is false and
If false, attempting to create a subscription that already exists will
fail.
To use this design more effectively, I would suggest the following:
var pubsub = require('gcloud').pubsub({
"projectId" : "project-id",
"keyFilename" : "key-file.json"
});
// This topic should already have been created
var topic = pubsub.topic("interesting-topic");
// The message that will be published
var message = {"data": "Welcome to this interesting thread"};
// Callback to throw an exception if publish was unsuccessful
// Will log published message IDs if successful
function publishedHandler(err, messageIds, responseBody) {
if (err) {
// Could not publish message(s)
throw err;
}
console.log(messagesIds);
}
// Callback to throw an exception if a subscription could not be found or created
// Will attach event listeners if successfully gets a subscription
function subscriptionHandler(err, subscription, responseBody) {
if (err) {
// Could not get or create a new subscription
throw err;
}
subscription.on("error", errorHandler);
subscription.on("message", messageHandler);
}
// Publish a message to the topic
topic.publish(message, publishedHandler);
// Create or get 'sub' and subcribe it to 'interesting-topic'
topic.subscribe("sub", {"reuseExisting": true}, subscriptionHandler);
Issue 696 may not refer exactly to this issue but does discuss some of the semantic choices made in designing the Node.js library for Cloud PubSub. It's not entirely clear if methods like topic.publish or topic.subscribe check for existence of a topic, existence of a subscription, create a new subscription or get an existing subscription. I would simply warn to add robust error handling.
Currently you do not check for errors, when subscribing, but just errors while being subscribed. To change that, you can use something like this:
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// first check for errors
if( err ) {
// something went wrong, react!
return;
}
// rest of your code
});

Express server crashing due to MongoDB connection loss

I am having issues with an HTTP Node.js server built with:
Ubuntu 14.04
MongoDB 3.0.4
iojs v2.3.3
express=4.10.*
mongodb=1.4.34
The following middleware are being used:
app.use(response_time());
app.use(body_parser.urlencoded({extended: true}));
app.use(body_parser.json());
var MongoClient = require('mongodb').MongoClient;
app.use(function (req, res, next) {
var connection_options = {auto_reconnect: false};
MongoClient.connect(config.server.db, connection_options, function (err, db) {
if (err) {
log.error(err); // Logging error.
return next(err);
}
req.db = db;
next();
});
});
The server started running at 20:40:10 and successfully handled multiple requests.
At 02:59:02, the following error started to get logged on every request:
02:59:02.114Z ERROR CrowdStudy: failed to connect to [127.0.0.1:27017]
Error: failed to connect to [127.0.0.1:27017]
at null.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/server.js:555:74)
at emitThree (events.js:97:13)
at emit (events.js:175:7)
at null.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:156:15)
at emitTwo (events.js:87:13)
at emit (events.js:172:7)
at Socket.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/connection.js:534:10)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at emitErrorNT (net.js:1237:8)
My initial suspicion was that I was that the connection pool was filling up because I don't have anything to handle calling req.db.close(). I thought that passing in the options {auto_reconnect: false} would fix this issue by automatically closing the connection after some time, but it seems I was wrong.
Note that restarting the server fixes the issue, so I believe the problem has to do with Node rather than Mongo.
If this has to do with the connection pool, is there some setting I can pass to fix this, or can I have an end-ware that makes sure the connection always gets closed?
Thanks a lot to anyone who can help me out!
autoReconnect is an option that should be passed to the server configuration:
MongoClient.connect(config.server.db, {
server : { autoReconnect : false }
}, ...);
The documentation contains some errors: it states that the default setting is false (which it isn't), and it also states that autoReconnect should be set in an object called socketOptions (which it shouldn't).
You can add various event listeners to the db object that gets passed back, to detect when the connection to the database got closed/reconnected/...:
db.on('close', function(reason) { ... });
db.on('reconnect', function(db) { ... });
More events here.