• The main problem is the type’s property is not present in all elements in the lesson array. Simply you can put the condition in arrayFilters that type exists or not.
  • Need to put the condition for lession id in arrayFilters
programId = "661e73b6ce3f2ab386a54b05"
lessonId = "65041daffd06fdef62a1117b"
type = "pdf"
mediaId = "65041d9ffd06fdef62a1116f"
updatedDoc = await UserProgram.updateOne(
      {
        "_id": programId,
        "lesson": {
          $elemMatch: {
            $elemMatch: { "_id": lessonId, [`${type}.mediaId`]: mediaId }
          }
        }
      },
      {
        $set: {
          [`lesson.$[].$[lesson].${type}.$[item].isRead`]: true
        }
      },
      {
        arrayFilters: [
          {
            "lesson._id": lessonId,
            [`lesson.${type}`]: {
              $exists: true
            }
          },
          { "item.mediaId": mediaId }
        ],
        new: true,
        timestamps: false // Disable automatic timestamps
      }
    );

Playground

Your schema is not well designed as per your use case, You can improve by using attribute pattern if possible.