Thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("expected value"

thread 'main' panicked at 'called Result::unwrap() on an Err value: Error("expected value", line: 1, column: 1)', src/models.rs:43:38
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/libunwind.rs:86
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:59
4: core::fmt::write
at src/libcore/fmt/mod.rs:1076
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1537
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:62
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:49
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:198
9: std::panicking::default_hook
at src/libstd/panicking.rs:217
10: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:526
11: rust_begin_unwind
at src/libstd/panicking.rs:437
12: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
13: core::option::expect_none_failed
at src/libcore/option.rs:1269
14: <std::collections::hash::map::HashMap<i32,hrdiff::models::Employee> as hrdiff::models::Objects>::all
15: <std::collections::hash::map::HashMapalloc::string::String,hrdiff::models::Diff as hrdiff::models::Objects>::all
16: hrdiff::view_diff
17: hrdiff::main
18: std::rt::lang_start::{{closure}}
19: std::rt::lang_start_internal::{{closure}}
at src/libstd/rt.rs:52
20: std::panicking::try::do_call
at src/libstd/panicking.rs:348
21: std::panicking::try
at src/libstd/panicking.rs:325
22: std::panic::catch_unwind
at src/libstd/panic.rs:394
23: std::rt::lang_start_internal
at src/libstd/rt.rs:51
24: main
25: __libc_start_main
26: _start
I have a parser for synchronization from 1c server to active directories!
sync stopped working and displays this error,
data for synchronization partially works out displays this error and there are links on which you check the parser there is an error about: The page was not displayed because there was a conflict.

So I don’t know rust, I have an error in the code or when receiving data?

The configurations are in the cargo files

https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap

When a Result is unwrapped it means that the program cannot deal with a Result::Err so it will panic and end the program. Result::unwrap is used in tests or when the coder knows it is logically impossible for it to be an Err. Even if the program is supposed to fail in such an event it’s good practice to provide a useful error message that helps a human figure out how to use the program without errors.

So the program is doing exactly what it was told to do: panic when it encounters an error. Unfortunately this error scenario does not provide a message that explains what you should do. You could ask the maintainer, but it looks like the program expects something different than what it’s getting.

1 Like

Well, what and where can I provide you to understand why the program breaks,
As soon as I understand, I have three scenarios

  1. /target/release/hrdiff view dep
  2. /target/release/hrdiff view emp
  3. /target/release/hrdiff view user
    when starting 1 and 2, I get the same error when running 3, I get some kind of result with users
    here is the models.rs code
pub trait Objects {
    fn all(&mut self, config: &Config);
}

extern crate serde_json;

use crate::config::Config;
use crate::rep::{get_deps, get_emps, get_users, write_user};
use ldap3::{LdapResult, SearchEntry};
use serde::Deserialize;
use std::collections::HashMap;
use std::fmt;

#[derive(Deserialize)]
#[allow(non_snake_case)]
pub struct Employee {
    pub id: String,
    pub Employee_id: String,
    pub Name: EmployeeName,
    pub Title: Title,
    pub Manager: String,
    pub Department: String,
    pub state: String,
}

#[derive(Deserialize)]
#[allow(non_snake_case)]
pub struct EmployeeName {
    pub Ru: String,
    pub En: String,
}

#[derive(Deserialize)]
#[allow(non_snake_case)]
pub struct Title {
    pub Ru: String,
    pub En: String,
    pub Kz: String,
}

impl Objects for HashMap<i32, Employee> {
    fn all(&mut self, config: &Config) {
        let emps = get_emps(&config).unwrap();
        for emp in emps {
            let key: i32 = emp.id.trim().parse().unwrap();
            if let Some(_u) = self.get(&key) {
                println!("Duplicating emp ID: {}", key);
            } else {
                self.insert(key, emp);
            }
        }
    }
}
impl fmt::Display for Employee {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}, {}", self.Name.Ru, self.state)
    }
}

#[derive(Deserialize)]
#[allow(non_snake_case)]
pub struct Dep {
    pub id: String,
    pub name: DepName,
    pub Supervisor: String,
    pub mvz: String,
}

#[derive(Deserialize)]
pub struct DepName {
    pub ru: String,
    pub en: String,
    pub kz: String,
}

impl Objects for HashMap<i32, Dep> {
    fn all(&mut self, config: &Config) {
        let deps = get_deps(&config).unwrap();
        for dep in deps {
            let key: i32 = dep.id.trim().parse().unwrap();
            if let Some(_u) = self.get(&key) {
                println!("Duplicating dep ID: {}", key);
            } else {
                self.insert(key, dep);
            }
        }
    }
}

impl fmt::Display for Dep {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name.ru)
    }
}
pub struct User {
    pub id: i32,
    pub employee_id: String,
    pub name_ru: String,
    pub name_en: String,
    pub title_ru: String,
    pub title_en: String,
    pub title_kz: String,
    pub manager: i32,
    pub manager_dn: String,
    pub department: i32,
    pub department_ru: String,
    pub department_en: String,
    pub department_kz: String,
    pub mvz: String,
    pub dn: String,
}

impl User {
    fn default() -> User {
        User {
            id: 0,
            employee_id: String::from(""),
            name_ru: String::from(""),
            name_en: String::from(""),
            title_ru: String::from(""),
            title_en: String::from(""),
            title_kz: String::from(""),
            manager: 0,
            manager_dn: String::from(""),
            department: 0,
            department_ru: String::from(""),
            department_en: String::from(""),
            department_kz: String::from(""),
            mvz: String::from(""),
            dn: String::from(""),
        }
    }
    fn new(user: &SearchEntry) -> User {
        let mut result = User::default();

        if let Some(v) = user.attrs.get("employeeID") {
            println!("{}", v[0]);
            result.id = v[0].parse().unwrap();
        }
        if let Some(v) = user.attrs.get("employeeNumber") {
            result.employee_id = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute4") {
            result.name_ru = v[0].clone();
        }
        if let Some(v) = user.attrs.get("cn") {
            result.name_en = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute6") {
            result.title_ru = v[0].clone();
        }
        if let Some(v) = user.attrs.get("title") {
            result.title_en = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute5") {
            result.title_kz = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute10") {
            result.manager = v[0].trim().parse().unwrap();
        }
        if let Some(v) = user.attrs.get("manager") {
            result.manager_dn = v[0].clone();
        }
        if let Some(v) = user.attrs.get("department") {
            result.department_en = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute12") {
            result.department_ru = v[0].clone();
        }
        if let Some(v) = user.attrs.get("extensionAttribute11") {
            result.department_kz = v[0].clone();
        }
        if let Some(v) = user.attrs.get("departmentNumber") {
            result.department = v[0].parse().unwrap();
        }
        if let Some(v) = user.attrs.get("mVZ") {
            result.mvz = v[0].clone();
        }
        result.dn = user.dn.clone();

        result
    }
}
impl Objects for HashMap<i32, User> {
    fn all(&mut self, config: &Config) {
        let users = get_users(&config).unwrap();

        for user in users {
            let plain_user = User::new(&user);
            if let Some(_u) = self.get(&plain_user.id) {
                println!("Duplicating user ID: {}", plain_user.id);
            } else {
                self.insert(plain_user.id, plain_user);
            }
        }
    }
}

impl fmt::Display for User {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name_ru)
    }
}

pub struct Replace(pub String, pub String, pub String);

pub struct Diff {
    pub dn: String,
    pub replace: Vec<Replace>,
}

impl Diff {
    pub fn push_changes(&self, config: &Config) -> LdapResult {
        write_user(&config, &self.dn, &self.replace).unwrap()
    }
}
impl Objects for HashMap<String, Diff> {
    fn all(&mut self, config: &Config) {
        let mut users_hash: HashMap<i32, User> = HashMap::new();
        users_hash.all(&config);

        let mut emps_hash: HashMap<i32, Employee> = HashMap::new();
        emps_hash.all(&config);

        let mut deps_hash: HashMap<i32, Dep> = HashMap::new();
        deps_hash.all(&config);

        for (_id, user) in &users_hash {
            if let Some(emp) = emps_hash.get(&user.id) {
                if emp.state != "work" {
                    println!("Need to disable user with ID: {}, {}", &user.id, &user.name_en);
                };
                let dep_id: i32 = emp.Department.trim().parse().unwrap();
                if let Some(dep) = deps_hash.get(&dep_id) {
                    let mut user_diff = Diff {
                        dn: user.dn.clone(),
                        replace: vec![],
                    };
                    if user.employee_id != emp.Employee_id.trim() {
                        let attr = String::from("employeeNumber");
                        let old = user.employee_id.clone();
                        let new = emp.Employee_id.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.name_ru != emp.Name.Ru.trim() {
                        let attr = String::from("extensionAttribute4");
                        let old = user.name_ru.clone();
                        let new = emp.Name.Ru.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.title_ru != emp.Title.Ru.trim() {
                        let attr = String::from("extensionAttribute6");
                        let old = user.title_ru.clone();
                        let new = emp.Title.Ru.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.title_en != emp.Title.En.trim() {
                        let attr = String::from("title");
                        let old = user.title_en.clone();
                        let new = emp.Title.En.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }
if user.title_kz != emp.Title.Kz.trim() {
                        let attr = String::from("extensionAttribute5");
                        let old = user.title_kz.clone();
                        let new = emp.Title.Kz.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.department_en != dep.name.en.trim() {
                        let attr = String::from("department");
                        let old = user.department_en.clone();
                        let new = dep.name.en.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.department_ru != dep.name.ru.trim() {
                        let attr = String::from("extensionAttribute12");
                        let old = user.department_ru.clone();
                        let new = dep.name.ru.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.department_kz != dep.name.kz.trim() {
                        let attr = String::from("extensionAttribute11");
                        let old = user.department_kz.clone();
                        let new = dep.name.kz.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.department != dep_id {
                        let attr = String::from("departmentNumber");
                        let old = user.department.to_string();
                        let new = dep_id.to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if user.mvz != dep.mvz.trim() {
                        let attr = String::from("mVZ");
                        let old = user.mvz.clone();
                        let new = dep.mvz.trim().clone().to_string();
                        user_diff.replace.push(Replace(attr, old, new));
                    }

                    if let Ok(manager_id) = emp.Manager.trim().parse::<i32>() {
                        if user.manager != manager_id {
                            let attr = String::from("extensionAttribute10");
                            let old = user.manager.to_string();
                            let new = manager_id.to_string();
                            user_diff.replace.push(Replace(attr, old, new));
                        }
 if let Some(manager) = users_hash.get(&manager_id) {
                            if user.manager_dn != manager.dn {
                                let attr = String::from("manager");
                                let old = user.manager_dn.clone();
                                let new = manager.dn.clone();
                                user_diff.replace.push(Replace(attr, old, new));
                            }
                        } else {
                            // Если не удалось найти менеджера в LDAP по табельному, то ищем по employeeNumber
                            if let Some(hr_manager) = emps_hash.get(&manager_id) {
                                let wd = hr_manager.Employee_id.trim();

                                if let Some(ldap_manager) =
                                    users_hash.iter().find(|(_key, man)| man.employee_id == wd)
                                {
                                    let (_id, manager_by_wd) = ldap_manager;
                                    if user.manager_dn != manager_by_wd.dn {
                                        let attr = String::from("manager");
                                        let old = user.manager_dn.clone();
                                        let new = manager_by_wd.dn.clone();
                                        user_diff.replace.push(Replace(attr, old, new));
                                    }
                                } else {
                                    println!(
                                        "Unable to find manager in LDAP with employeeNumber: {}",
                                        wd
                                    );
                                }
                            } else {
                                println!("Unable to find manager in HR with ID: {}", manager_id);
                            }
                        }
                    }

                    if user_diff.replace.len() > 0 {
                        self.insert(user.dn.clone(), user_diff);
                    }
                }
            }
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn get_emps_hash() {
        let config = Config::new().unwrap();
        let mut emps_hash: HashMap<i32, Employee> = HashMap::new();
        emps_hash.all(&config);
        assert_ne!(emps_hash.len(), 0)
    }

    #[test]
    fn get_deps_hash() {
        let config = Config::new().unwrap();
        let mut deps_hash: HashMap<i32, Dep> = HashMap::new();
        deps_hash.all(&config);
        assert_ne!(deps_hash.len(), 0)
    }

    #[test]
    fn get_users_hash() {
        let config = Config::new().unwrap();
        let mut users_hash: HashMap<i32, User> = HashMap::new();
        users_hash.all(&config);
        assert_ne!(users_hash.len(), 0)
    }

    #[test]
    fn get_diff_hash() {
        let config = Config::new().unwrap();
        let mut diff_hash: HashMap<String, Diff> = HashMap::new();
        diff_hash.all(&config);
        assert_ne!(diff_hash.len(), 0)
    }
}

Any Ideas?

The Objects implementation for HashMap<i32, Employee> has the following code:

impl Objects for HashMap<i32, Employee> {
    fn all(&mut self, config: &Config) {
        let emps = get_emps(&config).unwrap();
        for emp in emps {
            let key: i32 = emp.id.trim().parse().unwrap();
            if let Some(_u) = self.get(&key) {
                println!("Duplicating emp ID: {}", key);
            } else {
                self.insert(key, emp);
            }
        }
    }
}

Every time you write foo().unwrap() it's like saying "this foo() call may have returned an error, but I'm going to ignore it and crash the program when something goes wrong".

And now you are seeing your program crash.

The solution is to remove the unwrap() and handle the fact that get_emps() or emp.id.trim().parse() may fail. This is typically done by matching on the result or using ? to bubble the error up.

1 Like