{"record":{"id":"ee7e2aa799173ef1","repo":"sigoden/aichat","slug":"unknown-role-name","errorCode":null,"errorMessage":"Unknown role `{name}`","messagePattern":"Unknown role `(.+?)`","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/config/role.rs","lineNumber":96,"sourceCode":"                if let Some(value) = value.as_object() {\n                    for (key, value) in value {\n                        match key.as_str() {\n                            \"model\" => role.model_id = value.as_str().map(|v| v.to_string()),\n                            \"temperature\" => role.temperature = value.as_f64(),\n                            \"top_p\" => role.top_p = value.as_f64(),\n                            \"use_tools\" => role.use_tools = value.as_str().map(|v| v.to_string()),\n                            _ => (),\n                        }\n                    }\n                }\n            }\n        }\n        role\n    }\n\n    pub fn builtin(name: &str) -> Result<Self> {\n        let content = RolesAsset::get(&format!(\"{name}.md\"))\n            .ok_or_else(|| anyhow!(\"Unknown role `{name}`\"))?;\n        let content = unsafe { std::str::from_utf8_unchecked(&content.data) };\n        Ok(Role::new(name, content))\n    }\n\n    pub fn list_builtin_role_names() -> Vec<String> {\n        RolesAsset::iter()\n            .filter_map(|v| v.strip_suffix(\".md\").map(|v| v.to_string()))\n            .collect()\n    }\n\n    pub fn list_builtin_roles() -> Vec<Self> {\n        RolesAsset::iter()\n            .filter_map(|v| Role::builtin(&v).ok())\n            .collect()\n    }\n\n    pub fn has_args(&self) -> bool {\n        self.name.contains('#')","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/config/role.rs#L78-L114","documentation":"Role::builtin loads an embedded role markdown asset by name ('{name}.md'); if the asset is absent, the name is not a known built-in role. The error surfaces the requested name so the caller can correct it.","triggerScenarios":"Calling Role::builtin(name) where RolesAsset::get returns None, i.e. name doesn't match any embedded role file (exact, case-sensitive match required).","commonSituations":"Typo in role name in config or CLI flag; passing a custom role name to builtin instead of loading it from disk; version where the role was renamed or removed.","solutions":["Run the companion list_builtin_role_names() to see valid names and pick one","Fix the typo / casing in the role name","If you need a custom role, load it from a file instead of Role::builtin"],"exampleFix":"// before\nlet role = Role::builtin(\"assistent\")?;\n// after\nlet role = Role::builtin(\"assistant\")?;","handlingStrategy":"fallback","validationCode":"fn is_builtin_role(name: &str) -> bool {\n    Role::list_builtin_role_names().iter().any(|n| n == name)\n}","typeGuard":null,"tryCatchPattern":"let role = Role::builtin(name)\n    .or_else(|_| load_role_from_file(name))\n    .with_context(|| format!(\"role '{}' not found; available: {:?}\", name, Role::list_builtin_role_names()))?;","preventionTips":["Validate role names against list_builtin_role_names() at startup","Store role names as constants/enums instead of free strings","Remember matching is exact and case-sensitive"],"tags":["config","roles","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}