diff --git a/lib/myprofilelib.php b/lib/myprofilelib.php
index a341fbf51c4..4c5e09d6ccb 100644
--- a/lib/myprofilelib.php
+++ b/lib/myprofilelib.php
@@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool
  */
 function core_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) {
-    global $CFG, $USER, $DB;
+    global $CFG, $USER, $DB, $PAGE;
 
     $usercontext = context_user::instance($user->id, MUST_EXIST);
     $systemcontext = context_system::instance();
@@ -101,8 +101,8 @@ function core_myprofile_navigation(core_user\output\myprofile\tree $tree, $user,
         }
     }
 
-    // Preference page. Only visible by administrators.
-    if (!$iscurrentuser && is_siteadmin()) {
+    // Preference page.
+    if (!$iscurrentuser && $PAGE->settingsnav->can_view_user_preferences($user->id)) {
         $url = new moodle_url('/user/preferences.php', array('userid' => $user->id));
         $title = get_string('preferences', 'moodle');
         $node = new core_user\output\myprofile\node('administration', 'preferences', $title, null, $url);
diff --git a/lib/navigationlib.php b/lib/navigationlib.php
index 19284f772ed..d60c461de31 100644
--- a/lib/navigationlib.php
+++ b/lib/navigationlib.php
@@ -4773,6 +4773,33 @@ class settings_navigation extends navigation_node {
     public function clear_cache() {
         $this->cache->volatile();
     }
+
+    /**
+     * Checks to see if there are child nodes available in the specific user's preference node.
+     * If so, then they have the appropriate permissions view this user's preferences.
+     *
+     * @since Moodle 3.0
+     * @param int $userid The user's ID.
+     * @return bool True if child nodes exist to view, otherwise false.
+     */
+    public function can_view_user_preferences($userid) {
+        if (is_siteadmin()) {
+            return true;
+        }
+        // See if any nodes are present in the preferences section for this user.
+        $preferencenode = $this->find('userviewingsettings' . $userid, null);
+        if ($preferencenode && $preferencenode->has_children()) {
+            // Run through each child node.
+            foreach ($preferencenode->children as $childnode) {
+                // If the child node has children then this user has access to a link in the preferences page.
+                if ($childnode->has_children()) {
+                    return true;
+                }
+            }
+        }
+        // No links found for the user to access on the preferences page.
+        return false;
+    }
 }
 
 /**
diff --git a/user/preferences.php b/user/preferences.php
index f0895cabf04..d4b736e37ad 100644
--- a/user/preferences.php
+++ b/user/preferences.php
@@ -33,11 +33,6 @@ if (isguestuser()) {
 $userid = optional_param('userid', $USER->id, PARAM_INT);
 $currentuser = $userid == $USER->id;
 
-// Only administrators can access another user's preferences.
-if (!$currentuser && !is_siteadmin($USER)) {
-    throw new moodle_exception('cannotedituserpreferences', 'error');
-}
-
 // Check that the user is a valid user.
 $user = core_user::get_user($userid);
 if (!$user || !core_user::is_real_user($userid)) {
@@ -53,10 +48,16 @@ $PAGE->set_heading(fullname($user));
 
 if (!$currentuser) {
     $PAGE->navigation->extend_for_user($user);
-    $settings = $PAGE->settingsnav->find('userviewingsettings' . $user->id, null);
-    $settings->make_active();
+    // Need to check that settings exist.
+    if ($settings = $PAGE->settingsnav->find('userviewingsettings' . $user->id, null)) {
+        $settings->make_active();
+    }
     $url = new moodle_url('/user/preferences.php', array('userid' => $userid));
     $navbar = $PAGE->navbar->add(get_string('preferences', 'moodle'), $url);
+    // Show an error if there are no preferences that this user has access to.
+    if (!$PAGE->settingsnav->can_view_user_preferences($userid)) {
+        throw new moodle_exception('cannotedituserpreferences', 'error');
+    }
 } else {
     // Shutdown the users node in the navigation menu.
     $usernode = $PAGE->navigation->find('users', null);