{"record":{"id":"dc1db6d19fac6888","repo":"Hmbown/CodeWhale","slug":"could-not-be-parsed-safely","errorCode":null,"errorMessage":"{} could not be parsed safely","messagePattern":"(.+?) could not be parsed safely","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2496,"sourceCode":"\nfn load_workspace_dotenv_credentials_from_path(path: &Path) -> Result<WorkspaceDotenvReport> {\n    let contents = read_stable_workspace_dotenv(path)?;\n    let text = std::str::from_utf8(&contents)\n        .map_err(|_| anyhow!(\"{} is not valid UTF-8\", path.display()))?;\n    if dotenv_has_variable_expansion(text) {\n        bail!(\n            \"{} uses variable expansion; workspace .env values must be literal to prevent ambient-secret substitution\",\n            path.display()\n        );\n    }\n\n    let mut report = WorkspaceDotenvReport {\n        path: path.to_path_buf(),\n        ..WorkspaceDotenvReport::default()\n    };\n    let entries = dotenvy::from_read_iter(std::io::Cursor::new(contents))\n        .collect::<std::result::Result<Vec<_>, _>>()\n        .map_err(|_| anyhow!(\"{} could not be parsed safely\", path.display()))?;\n    for entry in entries {\n        let (key, value) = entry;\n        if !is_workspace_dotenv_credential_key(&key) {\n            report.ignored.insert(key);\n            continue;\n        }\n        if std::env::var_os(&key).is_some() {\n            continue;\n        }\n\n        // SAFETY: this loader runs synchronously in `main` before the runtime\n        // owner or Tokio workers are spawned. No concurrent environment reader\n        // exists inside Codewhale, and later startup code treats this process\n        // environment as immutable.\n        unsafe { std::env::set_var(&key, value) };\n        report.loaded.insert(key);\n    }\n    Ok(report)","sourceCodeStart":2478,"sourceCodeEnd":2514,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/lib.rs#L2478-L2514","documentation":"Codewhale parses the validated .env text with dotenvy::from_read_iter and collects every entry into a Vec. If dotenvy's parser rejects any line, the whole load aborts with '{path} could not be parsed safely'. The all-or-nothing collect is deliberate: a half-loaded credential set is worse than none.","triggerScenarios":"A line dotenvy cannot parse: an unterminated quote (KEY=\"value), invalid characters in a key position, malformed export syntax, or control characters that survived the UTF-8 check.","commonSituations":"Hand-edited .env with a missing closing quote; a multi-line PEM key pasted without single-line quoting; a copy-paste that split or merged lines; stray full-width or invisible characters.","solutions":["Check every line for balanced quotes and a single KEY=VALUE shape; wrap values containing spaces or # in double quotes on one line","Keep PEM keys and long tokens on a single line, or store a file path instead of the literal secret","Remove stray characters introduced by copy-paste (smart quotes, line-break artifacts)","Lint the file by parsing each non-comment line as KEY=VALUE before rerunning"],"exampleFix":"# before\nPRIVATE_KEY=\"-----BEGIN KEY-----\nabc123\n-----END KEY-----\"\n\n# after\nPRIVATE_KEY_PATH=/etc/codewhale/key.pem","handlingStrategy":"validation","validationCode":"for (i, line) in text.lines().enumerate() {\n    let l = line.trim();\n    if l.is_empty() || l.starts_with('#') {\n        continue;\n    }\n    if !l.contains('=') {\n        eprintln!(\"line {} has no '='\", i + 1);\n    }\n    if let Some((_k, v)) = l.split_once('=') {\n        if v.matches('\"').count() % 2 == 1 {\n            eprintln!(\"line {} has unbalanced quotes\", i + 1);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep one KEY=VALUE pair per line","Quote values containing spaces or # characters","Store long secrets in files and reference the path instead of embedding them"],"tags":["rust","env","dotenv","parsing"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}