{"record":{"id":"36b31d85c7628a36","repo":"astral-sh/ruff","slug":"expected-a-utf-8-working-directory","errorCode":null,"errorMessage":"Expected a UTF-8 working directory","messagePattern":"Expected a UTF-8 working directory","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff/src/commands/analyze_graph.rs","lineNumber":36,"sourceCode":"use std::io::Write;\nuse std::path::{Path, PathBuf};\nuse std::sync::{Arc, Mutex};\n\n/// Generate an import map.\npub(crate) fn analyze_graph(\n    args: AnalyzeGraphArgs,\n    config_arguments: &ConfigArguments,\n) -> Result<ExitStatus> {\n    // Construct the \"default\" settings. These are used when no `pyproject.toml`\n    // files are present, or files are injected from outside the hierarchy.\n    let pyproject_config = resolve(config_arguments, None)?;\n    if pyproject_config.settings.analyze.preview.is_disabled() {\n        warn_user!(\"`ruff analyze graph` is experimental and may change without warning\");\n    }\n\n    // Write all paths relative to the current working directory.\n    let root =\n        SystemPathBuf::from_path_buf(CWD.clone()).expect(\"Expected a UTF-8 working directory\");\n\n    // Find all Python files.\n    let files = resolve_default_files(args.files, false);\n    let (mut paths, resolver) = project_files_in_path(&files, &pyproject_config, config_arguments)?;\n\n    // Filter to only Python files\n    paths.retain(|path| {\n        if let Ok(ResolvedFile::Root(path) | ResolvedFile::Nested(path)) = path {\n            matches!(SourceType::from(path), SourceType::Python(_))\n        } else {\n            true\n        }\n    });\n\n    if paths.is_empty() {\n        warn_user_once!(\"No Python files found under the given path(s)\");\n        return Ok(ExitStatus::Success);\n    }","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff/src/commands/analyze_graph.rs#L18-L54","documentation":"`ruff analyze graph` builds a project-wide import graph and writes all output paths relative to the current working directory. The command requires the CWD to be representable as UTF-8 (SystemPathBuf::from_path_buf fails on non-UTF-8 paths); when it is not, this expect panics instead of producing a graceful error.","triggerScenarios":"Running `ruff analyze graph` (with analyze preview not enabled, or after the experimental warning) from a directory whose absolute path contains non-UTF-8 bytes (e.g. invalid UTF-8 from locale issues or exotic filenames in the path).","commonSituations":"Working inside a directory created with non-UTF-8 bytes on Linux; environments where the process CWD is inherited from a path with invalid encoding; CI containers with odd mount-point names.","solutions":["cd to a directory whose full path is valid UTF-8 and re-run the command","Rename the offending ancestor directory/file to use only UTF-8 characters","Check the CWD with `pwd | iconv -t utf-8` / `echo $PWD | LC_ALL=C grep -axv '.*'` to locate the non-UTF-8 segment","Run from a project checkout located under a plain ASCII path such as /tmp or ~/src"],"exampleFix":"# before\n$ cd /data/$(printf 'bad\\xff')/project && ruff analyze graph\npanic: Expected a UTF-8 working directory\n# after\n$ cd /data/project && ruff analyze graph","handlingStrategy":"validation","validationCode":"import subprocess, sys\ncwd = subprocess.run(['pwd'], capture_output=True).stdout\ntry:\n    cwd.decode('utf-8')\nexcept UnicodeDecodeError:\n    sys.exit('CWD is not valid UTF-8; move to a UTF-8 path before running ruff analyze graph')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep projects under plain UTF-8/ASCII directory paths","Check `pwd` encodes as UTF-8 in CI before invoking ruff analyze","Avoid directory names produced by untrusted/legacy encodings"],"tags":["rust","panic","utf-8","cli","filesystem"],"backgroundTag":"non-utf8-path","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}