stalwartlabs/stalwart · critical
Failed to read {yaml_path:?}
Error message
Failed to read {yaml_path:?} What it means
This panic is raised by the build script of the `common` crate when it cannot read `resources/locales/i18n.yml`, the YAML file from which all localization strings are code-generated into `locales.rs`. Without this file the build cannot produce the locale constants, so the script aborts compilation immediately with the resolved absolute path in the message. It is a fail-fast guard rather than a recoverable error.
Source
Thrown at crates/common/build.rs:15
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::path::Path;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("locales.rs");
// Read the YAML file
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let repo_root = Path::new(&manifest_dir).parent().unwrap().parent().unwrap();
let yaml_path = repo_root.join("resources/locales/i18n.yml");
let yaml_content =
fs::read_to_string(&yaml_path).unwrap_or_else(|_| panic!("Failed to read {yaml_path:?}"));
let locales = parse_yaml(&yaml_content);
let generated_code = generate_locale_code(&locales);
fs::write(&dest_path, generated_code).expect("Failed to write generated locales.");
println!("cargo:rerun-if-changed={}", yaml_path.display());
}
fn parse_yaml(content: &str) -> HashMap<String, HashMap<String, String>> {
let mut result: HashMap<String, HashMap<String, String>> = HashMap::new();
let mut current_key = None;
for line in content.lines() {
if let Some((key, value)) = line.split_once(':') {
let is_translation = key
.as_bytes()View on GitHub (pinned to e962003857)
Solutions
- Verify `resources/locales/i18n.yml` exists at the repo root and restore it (e.g. `git checkout -- resources/locales/i18n.yml`).
- Build from the repository root layout so CARGO_MANIFEST_DIR is exactly two levels below the repo root; do not relocate the crate directory.
- Check that your sparse-checkout / CI artifact includes the `resources/` directory.
- Fix filesystem permissions on the resources directory if read access is denied.
Example fix
// If i18n.yml was deleted: // $ git restore resources/locales/i18n.yml // If building from a relocated crate, restore the layout: // before: vendor/common/ (repo root detection fails) // after: <repo>/crates/common/ with <repo>/resources/locales/i18n.yml present
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
let yaml = Path::new(env!("CARGO_MANIFEST_DIR")).ancestors().nth(2).unwrap().join("resources/locales/i18n.yml");
assert!(yaml.is_file(), "missing locale manifest: {}", yaml.display()); Try / catch
// build scripts cannot catch panics usefully; validate before reading:
let content = fs::read_to_string(&yaml_path).unwrap_or_else(|e|
panic!("Failed to read {yaml_path:?}: {e}")); Prevention
- Keep the crate in its canonical crates/<name> layout so the two-level parent walk finds the repo root.
- Ensure CI checkouts include the resources/ directory (avoid sparse checkout of it).
- Add a repo lint/test that asserts resources/locales/i18n.yml exists.
When it happens
Trigger: Running `cargo build` when the repo-root-relative path `<repo>/resources/locales/i18n.yml` does not exist or is unreadable. The path is derived from CARGO_MANIFEST_DIR by going up two parent directories, so building a copy of the crate that is no longer two levels below the repo root, or a checkout with sparse/filtered resources, will also fail.
Common situations: Incomplete git clones (sparse checkout, submodule-less checkout, download of a single crate without resources), packaging the crate into a vendored/offline directory layout that breaks the two-level parent assumption, deleting or renaming the i18n.yml during refactoring, or filesystem permission issues on the resources directory.
Understand the failure class
Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.
Related errors
- {key}: {language} has no plural categories while other langu
- {key}: {language} repeats the plural category {name:?}
- {key}: {language} is missing the required "other" plural cat
- Missing: {}
- Node id {node_id} exceeds {MAX_NODE_ID}, panicking to avoid
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/9b86c6d3887bce63.
Report an issue: GitHub.