Skip to content

APNS Error when Sending Live Activity Notification in Node.js #92

@ragul-pr

Description

@ragul-pr

I'm working on a Node.js application that sends live activity notifications using the apns2 library. However, I'm encountering an error when trying to send a notification. Below is the relevant code from my apns2_function.js file:

import { Host, Notification, Priority, PushType } from "apns2";
import { ApnsClient } from "apns2";
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from "url";

export const sendLiveActivityNotification = async (deviceToken, options) => {
  try {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);

    console.log("Sending live activity notification", {
      deviceToken,
      options,
    });

    if (!deviceToken) {
      throw new Error("Device token is required");
    }

    const {
      chargingTime = 0,
      soc = 0,
      energyDelivered = 0,
      chargingSpeed = 0,
      isEndEvent = false,
    } = options || {};

    const payload = {
      aps: {
        event: isEndEvent ? "end" : "update",
        ...(isEndEvent && {
          "dismissal-date": Math.floor(Date.now() / 1000),
        }),
        "content-state": {
          appGroupId: "group.charge_liveactivity",
          time: Number(chargingTime),
          soc: Number(soc),
          energyDelivered: Number(energyDelivered),
          chargingSpeed: Number(chargingSpeed),
        },
        timestamp: Math.floor(Date.now() / 1000),
      },
    };

    // Create the notification payload
    const notification = new Notification({
      token: deviceToken,
      pushType: PushType.liveactivity,
      topic: "topic",
      priority: Priority.immediate,
      expiration: 0,
      payload: payload,
    });

    const client = new ApnsClient({
      team: "*****",
      keyId: "*****",
      signingKey: fs.readFileSync(
        path.join(__dirname, "AuthKey_****.p8")
      ),
      defaultTopic: "topic",
      requestTimeout: 10000,
      keepAlive: true,
      host: Host.development,
    });

    console.log("Notification Payload:", JSON.stringify(payload, null, 2));

    try {
      const result = await client.send(notification);

      console.log("Live activity notification sent successfully", result);

      return {
        status: "success",
        data: result,
        timestamp: new Date().toISOString(),
      };
    } catch (sendError) {
      console.error("Notification Send Error:", {
        message: sendError.message,
        name: sendError.name,
        code: sendError.code,
        stack: sendError.stack,
      });

      if (sendError.response) {
        console.error("APNS Response Details:", {
          status: sendError.response.status,
          headers: sendError.response.headers,
          body: sendError.response.body,
        });
      }

      throw {
        status: "error",
        message: sendError.message || "Failed to send notification",
        details: sendError,
        timestamp: new Date().toISOString(),
      };
    }
  } catch (err) {
    // Catch-all error handling
    console.error("Comprehensive Notification Error", {
      message: err.message,
      name: err.name,
      code: err.code,
      stack: err.stack,
      fullError: err,
    });

    throw {
      status: "error",
      message: err.message || "Failed to send notification",
      details: err,
      timestamp: new Date().toISOString(),
    };
  }
};

When I attempt to send a notification, I receive the following error:

Notification Send Error: {
  message: 'APNS Error',
  name: 'Error',
  code: undefined,
  stack: 'Error: APNS Error\n' +
    '    at ApnsClient._handleServerResponse (file:///path/to/apns.js:84:23)\n' +
    '    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n' +
    '    at async sendLiveActivityNotification (file:///path/to/apns2_function.js:71:22)'
}

Additionally, I see an unhandled promise rejection warning:

[UnhandledPromiseRejection: 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().]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions