How can i get many details as possible about error using React Error boundry get error details? - node.js

Im tring to catch more details when error accuring.
when the error is accuring im using node api server to catch the error and save in log file.
i simulated a Network Error and tring to get many details as possible.
when i console.log the error in frontend im getting this:
withFormHandler.js:28 Uncaught Error: Error: Network Error
at Object.componentDidUpdate (withFormHandler.js:28)
...
but i cant send this information using my api.
all im getting in the server side is an empty object.
so how can i catch and send many details as possible about the error and write it to the log file?
this is my ErrorBoundry component:
class ErrorBoundary extends React.Component {
state = {
hasError: false,
error: { message: "", stack: "" },
info: { componentStack: "" },
};
static getDerivedStateFromError = (error) => {
return { hasError: true };
};
componentDidCatch = (error, info) => {
this.setState({ error, info });
axios
.get(`http://localhost:5001/api/logs/error`, {
params: {
error: error.message,
details: info,
// details:error ---> this is also not give me information i need
},
})
.catch(() => {});
};
render() {
const { hasError, error, info } = this.state;
const { children } = this.props;
return hasError ? <ErrorComponent message={error.message} /> : children;
}
}
this is the server side handle:
router.get("/error", (req, res) => {
const errorMessage = req.query.error;
const details = req.query.details; -----> return an empty object :(
const logFile = "./logs/debug.log";
if (errorMessage) {
let error = errorMessage + "\r\n" + details;
fs.appendFile(logFile, error, function (err) {
// callback or something
});
}
});

Related

Why am I only getting Mailgun.js error in Cloud Run?

I'm trying to send an email using Mailgun's npm client - Mailgun.js.
When sending in development mode, everything works correctly. But when I upload the Node server to Cloud Run, something breaks.
Here is the code in the sendEmail helper file:
import formData from 'form-data';
import Mailgun from 'mailgun.js';
const sendEmail = async ({ to, subject, text, attachment, scheduledDate }) => {
const mailgun = new Mailgun(formData);
const mg = mailgun.client({
username: 'api',
key: process.env.MAILGUN_KEY,
url: 'https://api.eu.mailgun.net'
});
const data = {
from: `<myemail#mydomain.com>`,
to,
subject,
text
};
if (attachment) {
data.attachment = attachment;
}
if (scheduledDate) {
data['o:deliverytime'] = new Date(scheduledDate).toUTCString();
}
try {
const result = await mg.messages.create(process.env.MAILGUN_DOMAIN, data);
if (result.status && result.status !== 200) {
throw ({ code: result.status, message: result.message });
}
return true;
} catch(err) {
console.log(err);
return { error: err };
}
};
export default sendEmail;
And then in another file:
import { Router } from 'express';
import generateInvoicePDF from '../helpers/generateInvoicePDF.js';
import sendEmail from '../helpers/sendEmail.js';
const router = Router();
router.post('/email', async (req, res, next) => {
try {
const file = await generateInvoicePDF(invoice);
if (file?.error) {
throw ({ code: pdf.error.code, message: pdf.error.message });
}
const email = await sendEmail({
to: 'testemail#example.com',
subject: 'Invoice',
text: 'Test',
attachment: { filename: 'Invoice', data: file }
});
if (email?.error) {
throw ({ code: email.error.code, message: email.error.message });
}
res.status(200).json({ success: true });
} catch(err) {
next(err);
}
});
export default router;
The error I get when in production mode in Cloud Run's logs is:
TypeError: fetch failed
at Object.processResponse (node:internal/deps/undici/undici:5575:34)
at node:internal/deps/undici/undici:5901:42
at node:internal/process/task_queues:140:7
at AsyncResource.runInAsyncScope (node:async_hooks:202:9)
at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) {
cause: TypeError: object2 is not iterable
at action (node:internal/deps/undici/undici:1661:39)
at action.next (<anonymous>)
at Object.pull (node:internal/deps/undici/undici:1709:52)
at ensureIsPromise (node:internal/webstreams/util:172:19)
at readableStreamDefaultControllerCallPullIfNeeded (node:internal/webstreams/readablestream:1884:5)
at node:internal/webstreams/readablestream:1974:7
}
Why the hell does it work in development mode on my local machine, but not when uploaded to Cloud Run?
For anyone struggling with something similar - I eventually figured out the problem.
On my local machine, where everything was working as expected, I'm using Node v16.15.0, whereas in the Dockerfile, I had specified
FROM node:latest
and therefore Cloud Run was using a newer version, which led to the problems...
I've now deployed using version 16.15.0 and everything works fine

Try and catch CATCH ERROR: ERROR STATUS: 403 (What the error is due to?)

I'm trying to deploy a smart contract, but before doing so I'm accessing${basePath}/build/ipfsMetasGeneric/_ipfsMetasResponse.json and picking up the metaData.metadata_uri to assign it to PREREVEAL_TOKEN_URI. It all works well until there (I can see on the terminal the console.log (PREREVEAL_TOKEN_URI)). But the app stop working right after as it catches an error and throws me the message CATCH ERROR: ERROR STATUS: 403.
I'm just quite puzzled since I don't understand why the try code runs all Ok but then throws me that error. I've hit a roadblock, would appreciate any help.
Thank you.
Code follows:
const path = require("path");
const basePath = process.cwd();
const fs = require("fs");
const yesno = require('yesno');
const {
fetchNoRetry,
} = require(`${basePath}/utils/functions/fetchWithRetry.js`);
let {
CHAIN,
GENERIC,
CONTRACT_NAME,
CONTRACT_SYMBOL,
METADATA_UPDATABLE,
ROYALTY_SHARE,
ROYALTY_ADDRESS,
MAX_SUPPLY,
MINT_PRICE,
TOKENS_PER_MINT,
OWNER_ADDRESS,
TREASURY_ADDRESS,
PUBLIC_MINT_START_DATE,
BASE_URI,
PREREVEAL_TOKEN_URI,
PRESALE_MINT_START_DATE,
PRESALE_WHITELISTED_ADDRESSES
} = require(`${basePath}/src/config.js`);
const deployContract = async () => {
const ok = await yesno({
question: `Is all REQUIRED contract information correct in config.js? (y/n):`,
default: null,
});
if(!ok) {
console.log("Exiting...");
process.exit(0);
}
if(GENERIC) {
try {
let jsonFile = fs.readFileSync(`${basePath}/build/ipfsMetasGeneric/_ipfsMetasResponse.json`);
let metaData = JSON.parse(jsonFile);
console.log (metaData);
if(metaData.response === "OK") {
if(!PREREVEAL_TOKEN_URI) {
PREREVEAL_TOKEN_URI = metaData.metadata_uri;
console.log (PREREVEAL_TOKEN_URI);
}
} else {
console.log('There is an issue with the metadata upload. Please check the /build/_ipfsMetasGeneric/_ipfsMetasResponse.json file for more information. Running "npm run upload_metadata" may fix this issue.');
}
} catch (err) {
console.log(`/build/_ipfsMetasGeneric/_ipfsMetasResponse.json file not found. Run "npm run upload_metadata" first.`);
console.log(`Catch: ${err}`);
process.exit(0);
}
} else {
try {
let jsonFile = fs.readFileSync(`${basePath}/build/ipfsMetas/_ipfsMetasResponse.json`);
let metaData = JSON.parse(jsonFile);
if(metaData.response === "OK") {
if(!BASE_URI) {
BASE_URI = metaData.metadata_directory_ipfs_uri;
}
} else {
console.log('There is an issue with the metadata upload. Please check the /build/_ipfsMetas/_ipfsMetasResponse.json file for more information. Running "npm run upload_metadata" may fix this issue.');
}
} catch (err) {
console.log(`/build/_ipfsMetasGeneric/_ipfsMetasResponse.json file not found. Run "npm run upload_metadata" first.`);
process.exit(0);
}
}
if (!fs.existsSync(path.join(`${basePath}/build`, "/contract"))) {
fs.mkdirSync(path.join(`${basePath}/build`, "contract"));
}
try {
const url = `https://api.nftport.xyz/v0/contracts/collections`;
const contract = {
chain: CHAIN.toLowerCase(),
name: CONTRACT_NAME,
symbol: CONTRACT_SYMBOL,
owner_address: OWNER_ADDRESS,
metadata_updatable: METADATA_UPDATABLE,
royalties_share: ROYALTY_SHARE,
royalties_address: ROYALTY_ADDRESS,
max_supply: MAX_SUPPLY,
mint_price: MINT_PRICE,
tokens_per_mint: TOKENS_PER_MINT,
treasury_address: TREASURY_ADDRESS,
public_mint_start_date: PUBLIC_MINT_START_DATE,
presale_mint_start_date: PRESALE_MINT_START_DATE,
base_uri: BASE_URI,
prereveal_token_uri: PREREVEAL_TOKEN_URI,
presale_whitelisted_addresses: PRESALE_WHITELISTED_ADDRESSES
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(contract),
};
const response = await fetchNoRetry(url, options);
fs.writeFileSync(`${basePath}/build/contract/_deployContractResponse.json`, JSON.stringify(response, null, 2));
if(response.response === "OK") {
console.log(`Contract deployment started.`);
} else {
console.log(`Contract deployment failed`);
}
console.log(`Check /build/contract/_deployContractResponse.json for more information. Run "npm run get_contract" to get the contract details.`);
} catch (error) {
console.log(`CATCH: Contract deployment failed`, `ERROR: ${error}`);
}
};
deployContract();

Nestjs | grpc : How to handle remote error from client side

Remote Server
#Catch(RpcException)
export class RpcExceptionHandler implements RpcExceptionFilter<RpcException> {
catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
return throwError(exception.getError());
}
}
#UseFilters(new RpcExceptionHandler())
#GrpcMethod('AppController', 'Accumulate')
async accumulate(numberArray: INumberArray, metadata: any): Promise<ISumOfNumberArray> {
throw new RpcException({
code: 5,
message: 'Data Not Found'
})
}
Client code
#Get('add')
async getSumc(#Query('data') data: number[]) {
try {
let ata = await this.grpcService.accumulate({ data });
return ata;
} catch (err) {
//logic here if error comes
return err;
}
}
Proto defination.
syntax = "proto3";
package app;
// Declare a service for each controller you have
service AppController {
// Declare an rpc for each method that is called via gRPC
rpc Accumulate (NumberArray) returns (SumOfNumberArray);
}
// Declare the types used above
message NumberArray {
repeated double data = 1;
}
message SumOfNumberArray {
double sum = 1;
}
If error comes it is not going to catch block, just showing the server error.
I want to catch the error if remote throwing any error.
Try this one:
#Get('add')
async getSumc(#Query('data') data: number[]) {
try {
let ata = await this.grpcService.accumulate({ data }).toPromise();
return ata;
} catch (e) {
throw new RpcException(e);
}
}
Example here

How to make kuzzle-device-manager plugin API actions works?

I successfully installed and loaded kuzzle-device-manager in the backend file:
import { Backend } from 'kuzzle';
import { DeviceManagerPlugin } from 'kuzzle-device-manager';
const app = new Backend('playground');
console.log(app.config);
const deviceManager = new DeviceManagerPlugin();
const mappings = {
updatedAt: { type: 'date' },
payloadUuid: { type: 'keyword' },
value: { type: 'float' }
}
deviceManager.devices.registerMeasure('humidity', mappings)
app.plugin.use(deviceManager)
app.start()
.then(async () => {
// Interact with Kuzzle API to create a new index if it does not already exist
console.log(' started!');
})
.catch(console.error);
But when i try to use controllers from that plugin for example device-manager/device with create action i get an error output.
Here is my "client" code in js:
const { Kuzzle, WebSocket } = require("kuzzle-sdk")
const kuzzle = new Kuzzle(
new WebSocket('KUZZLE_IP')
)
kuzzle.on('networkError', error => {
console.error('Network Error: ', error);
})
const run = async () => {
try {
// Connects to the Kuzzle server
await kuzzle.connect();
// Creates an index
const result = await kuzzle.query({
index: "nyc-open-data",
controller: "device-manager/device",
action: "create",
body: {
model: "model-1234",
reference: "reference-1234"
}
}, {
queuable: false
})
console.log(result)
} catch (error) {
console.error(error.message);
} finally {
kuzzle.disconnect();
}
};
run();
And the result log:
API action "device-manager/device":"create" not found
Note: The nyc-open-data index exists and is empty.
We apologize for this mistake in the documentation, the device-manager/device:create method is not available because the plugin is using auto-provisioning until the v2.
You should send a payload to your decoder, the plugin will automatically provision the device if it does not exists https://docs.kuzzle.io/official-plugins/device-manager/1/guides/decoders/#receive-payloads

How to return grpc error in nodejs

I want to return grpc error code and description in server-side. I have tried this
function sayHello(call, callback) {
callback({error: {code: 400, message: "invalid input"});
}
but I got this exception from client
{ Error: Unknown Error
at /home/thanh/email/node_modules/grpc/src/node/src/client.js:434:17 code: 2, metadata: Metadata { _internal_repr: {} } }
If I don't want to include error field in message definition like this.
message Hello {
string name = 1;
string error = 2; // don't want this
}
Then what is the proper way to send grpc error back to client ?
Change it to:
return callback({
code: 400,
message: "invalid input",
status: grpc.status.INTERNAL
})
As a supplement, GRPC only allowed 16 kinds of error. You can check all error code from its site: https://grpc.io/docs/guides/error/#error-status-codes.
And here I found an example code for NodeJs error handling: https://github.com/avinassh/grpc-errors/blob/master/node/server.js
To clarify what #avi and #murgatroid99 have said what you want to do is structure you callback like so:
import * as grpc from '#grpc/grpc-js';
try{
somethingThatThrowsAnError();
}catch(e){
return callback(
{
message: e ,
code: grpc.status.NOT_FOUND
},
null,
)
}
grpc.status.NOT_FOUND is just a integer, 5, and when the client gets an error response from the server you can read it off the err prop returned e.g.
const client = new MyServiceConstructor(
address,
grpc.credentials.createInsecure()
);
client.myMethod(
myRequest,
metadata ?? new grpc.Metadata(),
(error: string, response: T_RESPONSE_TYPE) => {
if (error) {
if(error.code === grpc.status.NOT_FOUND) {
return handleNotFound(error, myRequest)
}
return unknownError(error, myRequest)
}
return response
},
);

Resources